/* Monolith window class. * - by Richard W.M. Jones * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: ml_window.c,v 1.8 2003/04/30 13:15:34 rich Exp $ */ #include "config.h" #ifdef HAVE_STRING_H #include #endif #include #include #include #include #include "monolith.h" #include "ml_window.h" struct ml_window { pool pool; /* Pool for allocations. */ const char *windowid; /* Window ID. */ /* For ordinary windows: */ ml_widget w; /* Packed widget. */ int headers_flag; /* If set, emit start, end of page. */ const char *title; /* Title of the window. */ const char *stylesheet; /* Stylesheet for the window. */ const char *charset; /* Character encoding. */ int refresh; /* Refresh period (0 = no refresh). */ int scroll_to_x, scroll_to_y; /* Scroll to (x, y). */ /* For framesets: */ const char *rows, *cols; /* Layout. */ vector frames; /* Frames (vector of struct * ml_frame_description). */ vector actions; /* Action IDs (one per frame). */ /* For redirects. */ const char *uri; /* URI to redirect to. */ /* Javascript cookies to set (see _ml_window_set_cookie_with_javascript). */ vector js_cookies; }; static int next_window_id = 0; ml_window new_ml_window (ml_session session, pool pool) { ml_window w = pmalloc (pool, sizeof *w); w->pool = pool; w->w = 0; w->headers_flag = 1; w->title = 0; /* XXX Eventually take this from the default theme for the application? */ w->stylesheet = "/ml-styles/default.css"; w->charset = "utf-8"; w->refresh = 0; w->scroll_to_x = w->scroll_to_y = 0; w->rows = w->cols = 0; w->frames = 0; w->actions = 0; w->uri = 0; w->js_cookies = new_vector (pool, const char *); /* Register and set current window. */ w->windowid = pitoa (pool, ++next_window_id); _ml_session_set_current_window (session, w, w->windowid); return w; } void ml_window_pack (ml_window w, ml_widget _w) { w->w = _w; } void ml_window_set_headers_flag (ml_window w, int headers_flag) { w->headers_flag = headers_flag; } int ml_window_get_headers_flag (ml_window w) { return w->headers_flag; } void ml_window_set_title (ml_window w, const char *title) { w->title = title; } const char * ml_window_get_title (ml_window w) { return w->title; } void ml_window_set_stylesheet (ml_window w, const char *stylesheet) { w->stylesheet = stylesheet; } const char * ml_window_get_stylesheet (ml_window w) { return w->stylesheet; } void ml_window_set_charset (ml_window w, const char *_charset) { w->charset = _charset; } const char * ml_window_get_charset (ml_window w) { return w->charset; } void ml_window_set_refresh (ml_window w, int refresh) { w->refresh = refresh; } int ml_window_get_refresh (ml_window w) { return w->refresh; } void ml_window_scroll_to (ml_window w, int x, int y) { w->scroll_to_x = x; w->scroll_to_y = y; } static void update_actions (ml_window w, ml_session session); ml_window new_ml_frameset (ml_session session, pool pool, const char *rows, const char *cols, vector frames) { ml_window w = new_ml_window (session, pool); w->rows = rows; w->cols = cols; w->frames = frames; update_actions (w, session); return w; } void ml_frameset_set_description (ml_window w, ml_session session, const char *rows, const char *cols, vector frames) { w->rows = rows; w->cols = cols; w->frames = frames; update_actions (w, session); } void ml_frameset_set_title (ml_window w, const char *title) { w->title = title; } const char * ml_frameset_get_title (ml_window w) { return w->title; } static void update_actions (ml_window w, ml_session session) { int i; const char *actionid; struct ml_frame_description frame; if (w->actions) { /* Unregister the old actions. */ for (i = 0; i < vector_size (w->actions); ++i) { vector_get (w->actions, i, actionid); ml_unregister_action (session, actionid); } vector_clear (w->actions); } else w->actions = new_vector (w->pool, const char *); if (w->frames && vector_size (w->frames) > 0) { /* Register new actions. */ for (i = 0; i < vector_size (w->frames); ++i) { vector_get (w->frames, i, frame); actionid = ml_register_action (session, frame.fn, frame.data); vector_push_back (w->actions, actionid); } } } ml_window new_ml_redirect (ml_session session, pool pool, const char *uri) { ml_window w = new_ml_window (session, pool); w->uri = uri; return w; } void ml_redirect_set_uri (ml_window w, const char *uri) { w->uri = uri; } const char * ml_redirect_get_uri (ml_window w) { return w->uri; } void _ml_window_notify_begin_response (ml_window w) { vector_clear (w->js_cookies); } int _ml_window_get_response_code (ml_window w) { if (! w->uri) return 200; else return 301; } const char * _ml_window_get_response_name (ml_window w) { if (! w->uri) return "OK"; else return "Moved Permanently"; } /* To allow shared object scripts to be embedded in pages using * mod_include we must set the session cookie using Javascript. This * is because mod_include doesn't propagate the Set-Cookie header from * a #include to the outer set of headers. * * NB. 'cookie' is allocated on the thread pool. */ void _ml_window_set_cookie_with_javascript (ml_window w, const char *cookie) { vector_push_back (w->js_cookies, cookie); } static inline void set_cookies_with_javascript (ml_window w, io_handle io) { while (vector_size (w->js_cookies) > 0) { const char *cookie; vector_pop_front (w->js_cookies, cookie); io_fprintf (io, "\n", cookie); } } void _ml_window_send_headers (ml_window w, pool thread_pool, http_response http_response) { if (! w->uri) { /* Send the Content-Type: header. */ http_response_send_header (http_response, "Content-Type", psprintf (thread_pool, "text/html; charset=%s", w->charset)); /* Refresh period? */ if (w->refresh != 0) http_response_send_header (http_response, "Refresh", pitoa (thread_pool, w->refresh)); } else { /* Send the Location: header. */ http_response_send_header (http_response, "Location", w->uri); /* Send the Content-Length: header. */ http_response_send_header (http_response, "Content-Length", "0"); } } const char * _ml_window_get_windowid (ml_window w) { return w->windowid; } void _ml_window_repaint (ml_window w, ml_session session, io_handle io) { if (!w->frames && !w->uri) /* Ordinary window. */ { if (w->headers_flag) { io_fprintf (io, "\n" "\n" "\n"); if (w->title) io_fprintf (io, "%s\n", w->title); if (w->stylesheet) io_fprintf (io, "\n", w->stylesheet); io_fprintf (io, "\n"); } set_cookies_with_javascript (w, io); if (w->w) ml_widget_repaint (w->w, session, w->windowid, io); if (w->scroll_to_x > 0 || w->scroll_to_y > 0) { io_fprintf (io, "\n", w->scroll_to_x, w->scroll_to_y); } if (w->headers_flag) io_fprintf (io, "\n"); } else if (w->frames) /* Frameset. */ { int i; io_fprintf (io, "\n" "\n" "\n"); if (w->title) io_fprintf (io, "%s\n", w->title); io_fprintf (io, "rows) io_fprintf (io, " rows=\"%s\"", w->rows); if (w->cols) io_fprintf (io, " cols=\"%s\"", w->cols); io_fprintf (io, ">"); for (i = 0; i < vector_size (w->frames); ++i) { /* struct ml_frame_description frame; */ const char *actionid; /* vector_get (w->frames, i, frame); */ vector_get (w->actions, i, actionid); io_fprintf (io, "", ml_session_script_name (session), actionid); } io_fprintf (io, "\n"); } else /* Redirect. */ { /* Do nothing. */ } }