/* Copyright 1996 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. */ /*main.c - entry points for DrawFile module */ /*From CLib */ #include #include #include #include #include #include /*From OSLib */ #include "messagetrans.h" #include "macros.h" #include "os.h" #include "osfile.h" #include "osmodule.h" #include "resourcefs.h" /*From Support */ #include "m.h" #include "riscos.h" #include "jc_trace.h" /*Local */ #include "bbox.h" #include "declare.h" #include "main.h" #include "files.h" #include "render.h" #include "verify.h" typedef struct { int object_type; callback_fn *fn; } Association; static messagetrans_control_block Control_Block; static char *Message_Data; static Association Verification_Table[] = { {drawfile_TYPE_FONT_TABLE, &verify_font_table}, {drawfile_TYPE_GROUP, &verify_group}, {drawfile_TYPE_TEXT, &verify_text}, {drawfile_TYPE_TAGGED, &verify_tagged}, {drawfile_TYPE_TRFM_TEXT, &verify_trfm_text} }; static Association Rendering_Table[] = { {drawfile_TYPE_FONT_TABLE, &render_font_table}, {drawfile_TYPE_TEXT, &render_text}, {drawfile_TYPE_TEXT, &render_text_system}, {drawfile_TYPE_PATH, &render_path}, {drawfile_TYPE_SPRITE, &render_sprite}, {drawfile_TYPE_GROUP, &render_group}, {drawfile_TYPE_TAGGED, &render_tagged}, {drawfile_TYPE_TEXT_AREA, &render_text_area}, {drawfile_TYPE_TRFM_TEXT, &render_trfm_text}, {drawfile_TYPE_TRFM_TEXT, &render_trfm_text_system}, {drawfile_TYPE_TRFM_SPRITE, &render_trfm_sprite}, {drawfile_TYPE_JPEG, &render_jpeg} }; static Association Declaration_Table[] = { {drawfile_TYPE_FONT_TABLE, &declare_font_table}, {drawfile_TYPE_GROUP, &declare_group}, {drawfile_TYPE_TAGGED, &declare_tagged}, {drawfile_TYPE_TEXT_AREA, &declare_text_area} }; static os_trfm Identity = { { {0x10000, 0}, {0, 0x10000}, {0, 0}}}; callback_l main_verification_callback = NULL, main_render_callback = NULL, main_declaration_callback = NULL; #ifdef USE_ATEXIT /*------------------------------------------------------------------------*/ static void Exit(void) { (void) main_terminate(SKIP, SKIP, SKIP); } #endif /*------------------------------------------------------------------------*/ static os_error *Create_List(Association table[], int count, callback_l * l_out) { os_error *error = NULL; int i; callback_l l; bool done_new = FALSE; tracef("main_initialise: creating callback list\n"); if ((error = callback_new(&l)) != NULL) goto finish; done_new = TRUE; for (i = 0; i < count; i++) if ((error = callback_register(l, table[i].fn, NULL, 1, table[i].object_type)) != NULL) goto finish; if (l_out != NULL) *l_out = l; finish: if (error != NULL) { if (done_new) (void) callback_delete(l); } return error; } /*------------------------------------------------------------------------*/ _kernel_oserror *main_initialise(char *tail, int podule_base, void *workspace) { os_error *error = NULL; int size; bool done_open_file = FALSE; #ifdef STANDALONE bool done_register_files = FALSE; #endif bits flags; char *message_file_name; trace_initialise("DrawFile$Trace"); tracef("main_initialise\n"); tail = tail, podule_base = podule_base, workspace = workspace; if ((error = riscos_territory(territory_CURRENT)) != NULL) goto finish; #ifdef STANDALONE /* Register files. */ tracef("main_initialise: registering messages from data at 0x%X\n" _ files_messages()); if ((error = xresourcefs_register_files(files_messages())) != NULL) goto finish; done_register_files = TRUE; #endif tracef("main_initialise: looking up DrawFile$Path\n"); message_file_name = getenv("DrawFile$Path") == NULL ? "Resources:Resources.DrawFile.Messages" : "DrawFile:Messages"; if ((error = xmessagetrans_file_info(message_file_name, &flags, &size)) != NULL) goto finish; if ((flags & messagetrans_DIRECT_ACCESS) != 0) Message_Data = NULL; else { if ((Message_Data = m_ALLOC(size)) == NULL) { error = main_error_lookup(1, "NoMem"); goto finish; } } if ((error = xmessagetrans_open_file(&Control_Block, message_file_name, Message_Data)) != NULL) goto finish; done_open_file = TRUE; /* Make the verification callback list. */ tracef("main_initialise: creating verification callback list\n"); if ((error = Create_List(Verification_Table, COUNT(Verification_Table), &main_verification_callback)) != NULL || (error = Create_List(Rendering_Table, COUNT(Rendering_Table), &main_render_callback)) != NULL || (error = Create_List(Declaration_Table, COUNT(Declaration_Table), &main_declaration_callback)) != NULL) goto finish; #ifdef USE_ATEXIT atexit(&Exit); #endif finish: if (error != NULL) { callback_delete(main_declaration_callback); callback_delete(main_render_callback); callback_delete(main_verification_callback); if (done_open_file) { os_error *error1 = xmessagetrans_close_file(&Control_Block); if (error == NULL) error = error1; } m_FREE(Message_Data, size); #ifdef STANDALONE if (done_register_files) { os_error *error1 = xresourcefs_deregister_files ((resourcefs_file_list *) files_messages()); if (error == NULL) error = error1; } #endif } return (_kernel_oserror *) error; } /*------------------------------------------------------------------------*/ _kernel_oserror *main_terminate(int fatal, int instance, void *workspace) { fatal = fatal, instance = instance, workspace = workspace; tracef("main_terminate\n"); callback_delete(main_declaration_callback); callback_delete(main_render_callback); callback_delete(main_verification_callback); (void) xmessagetrans_close_file(&Control_Block); m_FREE(Message_Data, 0); #ifdef STANDALONE (void) xresourcefs_deregister_files(files_messages()); #endif trace_terminate(); return NULL; } /*------------------------------------------------------------------------*/ _kernel_oserror *main_swi(int swi, _kernel_swi_regs * regs, void *workspace) { os_error *error = NULL; tracef("main_swi\n"); workspace = workspace; if ((error = verify_diagram((drawfile_diagram *) regs->r[1], regs->r[2])) != NULL) goto finish; switch (swi) { case DrawFile_Render & 0x1F: tracef("main_swi: despatching Render\n"); if ((error = render((bits) regs->r[0], (drawfile_diagram *) regs->r[1], regs->r[2], regs->r[3] != 0 ? (os_trfm *) regs->r[3] : &Identity, (os_box *) regs->r[4], regs->r[5])) != NULL) goto finish; break; case DrawFile_BBox & 0x1F: tracef("main_swi: despatching BBox\n"); if ((error = bbox((bits) regs->r[0], (drawfile_diagram *) regs->r[1], regs->r[2], regs->r[3] != 0 ? (os_trfm *) regs->r[3] : &Identity, (os_box *) regs->r[4])) != NULL) goto finish; break; case DrawFile_DeclareFonts & 0x1F: tracef("main_swi: despatching DeclareFonts\n"); if ((error = declare((bits) regs->r[0], (drawfile_diagram *) regs->r[1], regs->r[2])) != NULL) goto finish; break; default: error = main_error_lookup(0x1E8, "BadSwi", "DrawFile"); goto finish; break; } finish: return (_kernel_oserror *) error; } /*------------------------------------------------------------------------*/ _kernel_oserror *main_service(int service, _kernel_swi_regs * regs, void *workspace) { bool unclaimed = TRUE; os_error *error = NULL; workspace = workspace; switch (service) { case Service_ResourceFSStarting: #ifdef STANDALONE tracef("main_service: servicing ResourceFSStarting\n"); (*(void (*)(resourcefs_file_list *, int, int, int)) regs->r[2]) (files_messages(), regs->r[1], regs->r[2], regs->r[3]); #endif break; case DrawFile_Render: switch (regs->r[0]) { case drawfile_TYPE_FONT_TABLE: render_font_table(NULL, (void *) regs->r[2], &unclaimed); break; case drawfile_TYPE_TEXT: render_text(NULL, (void *) regs->r[2], &unclaimed); break; case drawfile_TYPE_PATH: render_path(NULL, (void *) regs->r[2], &unclaimed); break; case drawfile_TYPE_SPRITE: render_sprite(NULL, (void *) regs->r[2], &unclaimed); break; case drawfile_TYPE_GROUP: render_group(NULL, (void *) regs->r[2], &unclaimed); break; case drawfile_TYPE_TAGGED: render_tagged(NULL, (void *) regs->r[2], &unclaimed); break; case drawfile_TYPE_TEXT_AREA: render_text_area(NULL, (void *) regs->r[2], &unclaimed); break; case drawfile_TYPE_TRFM_TEXT: render_trfm_text(NULL, (void *) regs->r[2], &unclaimed); break; case drawfile_TYPE_TRFM_SPRITE: render_trfm_sprite(NULL, (void *) regs->r[2], &unclaimed); break; case drawfile_TYPE_JPEG: render_jpeg(NULL, (void *) regs->r[2], &unclaimed); break; } if (!unclaimed) regs->r[1] = 0; break; default: error = main_error_lookup(0x1E8, "BadService", "DrawFile"); break; } return((_kernel_oserror *) error); } /*------------------------------------------------------------------------*/ _kernel_oserror *main_command(char *tail, int argc, int cmd_no, void *workspace) { os_error *error = NULL; tracef("main_command\n"); switch (cmd_no) { case main_COMMAND_RENDER: { /* Render */ os_trfm m; struct { char *file, *m[3][2]; bool bbox, suppress; char *flatness; char argd[1024]; } argl; int obj_type, size, flatness, i, j; drawfile_diagram *diagram = NULL; static int Scale[3][2] = { {1 << 16, 1 << 16}, {1 << 16, 1 << 16}, {draw_OS_UNIT, draw_OS_UNIT}}; NOT_USED(argc) NOT_USED(workspace) tracef("tail \"%.*s\"\n" _ riscos_strlen(tail) _ tail); if ((error = xos_read_args("file/a,m00,m01,m10,m11,m20,m21," "bbox/s,suppress/s,flatness/k", tail, (char *) &argl, sizeof argl, NULL)) != NULL) goto rendered; tracef("decoding is:\nfile \"%s\"\nm %s %s %s %s %s %s\n" "bbox %s\nsuppress %s\nflatness %s\n" _ argl.file _ argl.m[0][0] != NULL ? argl.m[0][0] : "NULL" _ argl.m[0][1] != NULL ? argl.m[0][1] : "NULL" _ argl.m[1][0] != NULL ? argl.m[1][0] : "NULL" _ argl.m[1][1] != NULL ? argl.m[1][1] : "NULL" _ argl.m[2][0] != NULL ? argl.m[2][0] : "NULL" _ argl.m[2][1] != NULL ? argl.m[2][1] : "NULL" _ WHETHER(argl.bbox) _ WHETHER(argl.suppress) _ argl.flatness != NULL ? argl.flatness : "NULL"); if ((error = xosfile_read_no_path(argl.file, &obj_type, NULL, NULL, &size, NULL)) != NULL) goto rendered; if (obj_type != osfile_IS_FILE) { error = xosfile_make_error(argl.file, obj_type); goto rendered; } /* Decode the matrix. */ for (j = 0; j < 2; j++) for (i = 0; i < 3; i++) if (argl.m[i][j] == NULL || riscos_scan_fixed (argl.m[i][j], &m.entries[i][j], Scale[i][j]) == 0) m.entries[i][j] = Identity.entries[i][j]; tracef("matrix ((0x%X 0x%X) (0x%X 0x%X) (%d %d))\n" _ m.entries[0][0] _ m.entries[0][1] _ m.entries[1][0] _ m.entries[1][1] _ m.entries[2][0] _ m.entries[2][1]); if (argl.flatness == NULL || riscos_scan_fixed(argl.flatness, &flatness, 256) == 0) flatness = -1; tracef("flatness %d\n" _ flatness); if ((diagram = m_ALLOC(size)) == NULL) { error = main_error_lookup(os_GLOBAL_NO_MEM, "NoMem"); goto rendered; } if ((error = xosfile_load_stamped_no_path(argl.file, (byte *) diagram, NULL, NULL, NULL, NULL, NULL)) != NULL) goto rendered; if ((error = verify_diagram(diagram, size)) != NULL) goto rendered; if ((error = render((argl.bbox ? drawfile_RENDER_BBOXES : NONE) | (argl.suppress ? drawfile_RENDER_SUPPRESS : NONE) | (flatness != -1 ? drawfile_RENDER_GIVEN_FLATNESS : NONE), diagram, size, &m, NULL, flatness)) != NULL) goto rendered; rendered: m_FREE(diagram, size); } break; } return (_kernel_oserror *) error; } /*------------------------------------------------------------------------*/ os_error *main_error_lookup(int no, char *token,...) { va_list list; char *p[4]; int i; os_error error; tracef("main_error_lookup\n"); /* Assume that 4 args are always given. */ va_start(list, token); for (i = 0; i < 4; i++) p[i] = va_arg(list, char *); va_end(list); error.errnum = no; strcpy(error.errmess, token); return xmessagetrans_error_lookup(&error, &Control_Block, NULL, 0, p[0], p[1], p[2], p[3]); }