Esempio n. 1
0
HRESULT navigate_url(DocHost *This, LPCWSTR url, const VARIANT *Flags,
                     const VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
{
    PBYTE post_data = NULL;
    ULONG post_data_len = 0;
    LPWSTR headers = NULL;
    HRESULT hres = S_OK;

    TRACE("navigating to %s\n", debugstr_w(url));

    if((Flags && V_VT(Flags) != VT_EMPTY) 
       || (TargetFrameName && V_VT(TargetFrameName) != VT_EMPTY))
        FIXME("Unsupported args (Flags %p:%d; TargetFrameName %p:%d)\n",
                Flags, Flags ? V_VT(Flags) : -1, TargetFrameName,
                TargetFrameName ? V_VT(TargetFrameName) : -1);

    if(PostData && V_VT(PostData) == (VT_ARRAY | VT_UI1) && V_ARRAY(PostData)) {
        SafeArrayAccessData(V_ARRAY(PostData), (void**)&post_data);
        post_data_len = V_ARRAY(PostData)->rgsabound[0].cElements;
    }

    if(Headers && V_VT(Headers) == VT_BSTR) {
        headers = V_BSTR(Headers);
        TRACE("Headers: %s\n", debugstr_w(headers));
    }

    set_doc_state(This, READYSTATE_LOADING);
    This->ready_state = READYSTATE_LOADING;

    if(This->doc_navigate) {
        WCHAR new_url[INTERNET_MAX_URL_LENGTH];

        if(PathIsURLW(url)) {
            new_url[0] = 0;
        }else {
            DWORD size;

            size = sizeof(new_url)/sizeof(WCHAR);
            hres = UrlApplySchemeW(url, new_url, &size, URL_APPLY_GUESSSCHEME);
            if(FAILED(hres)) {
                WARN("UrlApplyScheme failed: %08x\n", hres);
                new_url[0] = 0;
            }
        }

        hres = async_doc_navigate(This, *new_url ? new_url : url, headers, post_data,
                post_data_len, TRUE);
    }else {
        task_navigate_bsc_t *task;

        task = heap_alloc(sizeof(*task));
        task->bsc = create_callback(This, url, post_data, post_data_len, headers);
        push_dochost_task(This, &task->header, navigate_bsc_proc, This->url == NULL);
    }

    if(post_data)
        SafeArrayUnaccessData(V_ARRAY(PostData));

    return hres;
}
Esempio n. 2
0
static void
gtk2perl_cell_layout_set_cell_data_func (GtkCellLayout         *cell_layout,
                                         GtkCellRenderer       *cell,
                                         GtkCellLayoutDataFunc  func,
                                         gpointer               func_data,
                                         GDestroyNotify         destroy)
{
	GET_METHOD_OR_DIE (cell_layout, "SET_CELL_DATA_FUNC");

	{
		SV *code_sv, *data_sv;
		PREP (cell_layout);

		XPUSHs (sv_2mortal (newSVGtkCellRenderer (cell)));

		if (func) {
			create_callback (func, func_data, destroy,
					 &code_sv, &data_sv);

			XPUSHs (sv_2mortal (code_sv));
			XPUSHs (sv_2mortal (data_sv));
		}

		CALL;
		FINISH;
	}
}
Esempio n. 3
0
/*
 * Class:     org_java_gtk_gtk_Widget
 * Method:    gtk_widget_add_configure_event_handler
 * Signature: (JLorg/java_gtk/gtk/Widget/ConfigureEventHandler;Lorg/java_gtk/gtk/Widget;)V
 */
JNIEXPORT void JNICALL Java_org_java_1gtk_gtk_Widget_gtk_1widget_1add_1configure_1event_1handler
  (JNIEnv *env, jclass cls, jlong instance, jobject handler, jclass receiver)
{
	callback *c;
	long handle_id;
	c = create_callback(env, handler, receiver, "configureEventReceiver", "(Lorg/java_gtk/gtk/Widget$ConfigureEventHandler;JJ)Z");
	handle_id = connect_callback((gpointer)instance, "configure-event", G_CALLBACK(widget_event_handler), c);
	update_handle(env, handler, "setHandleId", "(J)V", handle_id);
}
Esempio n. 4
0
/*
 * Class:     org_java_gtk_gtk_Widget
 * Method:    gtk_widget_add_destroy_handler
 * Signature: (JLorg/java_gtk/gtk/Widget/DestroyHandler;Lorg/java_gtk/gtk/Widget;)V
 */
JNIEXPORT void JNICALL Java_org_java_1gtk_gtk_Widget_gtk_1widget_1add_1destroy_1handler
  (JNIEnv *env, jclass cls, jlong instance, jobject handler, jclass receiver)
{
	callback *c;
	long handle_id;
	c = create_callback(env, handler, receiver, "destroyReceiver", "(Lorg/java_gtk/gtk/Widget$DestroyHandler;J)V");
	handle_id = connect_callback((gpointer)instance, "destroy", G_CALLBACK(widget_destroy_handler), c);
	update_handle(env, handler, "setHandleId", "(J)V", handle_id);
}
Esempio n. 5
0
/*
 * Class:     org_java_gtk_gtk_ComboBox
 * Method:    gtk_combo_box_add_changed_event_handler
 * Signature: (JLorg/java_gtk/gtk/ComboBox/ChangedEventHandler;Ljava/lang/Class;)V
 */
JNIEXPORT void JNICALL Java_org_java_1gtk_gtk_ComboBox_gtk_1combo_1box_1add_1changed_1event_1handler
  (JNIEnv *env, jclass cls, jlong instance, jobject handler, jclass receiver)
{
	callback *c;
	long handle_id;
	c = create_callback(env, handler, receiver, "changedEventReceiver", "(Lorg/java_gtk/gtk/ComboBox$ChangedEventHandler;J)V");
	handle_id = (long)connect_callback((gpointer)instance, "changed", G_CALLBACK(combo_box_changed_event_handler), c);
	update_handle(env, handler, "setHandleId", "(J)V", handle_id);
}
Esempio n. 6
0
static HRESULT navigate_hlink(DocHost *This, IMoniker *mon, IBindCtx *bindctx,
                              IBindStatusCallback *callback)
{
    IHttpNegotiate *http_negotiate;
    BindStatusCallback *bsc;
    PBYTE post_data = NULL;
    ULONG post_data_len = 0;
    LPWSTR headers = NULL, url;
    BINDINFO bindinfo;
    DWORD bindf = 0;
    HRESULT hres;

    TRACE("\n");

    hres = IMoniker_GetDisplayName(mon, 0, NULL, &url);
    if(FAILED(hres))
        FIXME("GetDisplayName failed: %08x\n", hres);

    hres = IBindStatusCallback_QueryInterface(callback, &IID_IHttpNegotiate,
                                              (void**)&http_negotiate);
    if(SUCCEEDED(hres)) {
        static const WCHAR null_string[] = {0};

        IHttpNegotiate_BeginningTransaction(http_negotiate, null_string, null_string, 0,
                                            &headers);
        IHttpNegotiate_Release(http_negotiate);
    }

    memset(&bindinfo, 0, sizeof(bindinfo));
    bindinfo.cbSize = sizeof(bindinfo);

    hres = IBindStatusCallback_GetBindInfo(callback, &bindf, &bindinfo);
    dump_BINDINFO(&bindinfo);
    if(bindinfo.dwBindVerb == BINDVERB_POST) {
        post_data_len = bindinfo.cbstgmedData;
        if(post_data_len)
            post_data = bindinfo.stgmedData.u.hGlobal;
    }

    if(This->doc_navigate) {
        hres = async_doc_navigate(This, url, headers, post_data, post_data_len, FALSE);
    }else {
        bsc = create_callback(This, url, post_data, post_data_len, headers);
        hres = navigate_bsc(This, bsc, mon);
        IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface);
    }

    CoTaskMemFree(url);
    CoTaskMemFree(headers);
    ReleaseBindInfo(&bindinfo);

    return hres;
}
Esempio n. 7
0
HRESULT navigate_url(DocHost *This, LPCWSTR url, const VARIANT *Flags,
                     const VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
{
    task_navigate_bsc_t *task;
    PBYTE post_data = NULL;
    ULONG post_data_len = 0;
    LPWSTR headers = NULL;

    TRACE("navigating to %s\n", debugstr_w(url));

    if((Flags && V_VT(Flags) != VT_EMPTY) 
       || (TargetFrameName && V_VT(TargetFrameName) != VT_EMPTY))
        FIXME("Unsupported args (Flags %p:%d; TargetFrameName %p:%d)\n",
                Flags, Flags ? V_VT(Flags) : -1, TargetFrameName,
                TargetFrameName ? V_VT(TargetFrameName) : -1);

    if(PostData) {
        TRACE("PostData vt=%d\n", V_VT(PostData));

        if(V_VT(PostData) == (VT_ARRAY | VT_UI1)) {
            SafeArrayAccessData(V_ARRAY(PostData), (void**)&post_data);
            post_data_len = V_ARRAY(PostData)->rgsabound[0].cElements;
        }
    }

    if(Headers && V_VT(Headers) != VT_EMPTY && V_VT(Headers) != VT_ERROR) {
        if(V_VT(Headers) != VT_BSTR)
            return E_INVALIDARG;

        headers = V_BSTR(Headers);
        TRACE("Headers: %s\n", debugstr_w(headers));
    }

    task = heap_alloc(sizeof(*task));
    task->bsc = create_callback(This, url, post_data, post_data_len, headers);

    if(post_data)
        SafeArrayUnaccessData(V_ARRAY(PostData));

    push_dochost_task(This, &task->header, navigate_bsc_proc, This->url == NULL);

    return S_OK;
}
Esempio n. 8
0
HRESULT navigate_url(DocHost *This, LPCWSTR url, const VARIANT *Flags,
                     const VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
{
    SAFEARRAY *post_array = NULL;
    PBYTE post_data = NULL;
    ULONG post_data_len = 0;
    LPWSTR headers = NULL;
    HRESULT hres = S_OK;

    TRACE("navigating to %s\n", debugstr_w(url));

    if((Flags && V_VT(Flags) != VT_EMPTY && V_VT(Flags) != VT_ERROR)
       || (TargetFrameName && V_VT(TargetFrameName) != VT_EMPTY && V_VT(TargetFrameName) != VT_ERROR))
        FIXME("Unsupported args (Flags %s; TargetFrameName %s)\n", debugstr_variant(Flags), debugstr_variant(TargetFrameName));

    if(PostData) {
        if(V_VT(PostData) & VT_ARRAY)
            post_array = V_ISBYREF(PostData) ? *V_ARRAYREF(PostData) : V_ARRAY(PostData);
        else
            WARN("Invalid post data %s\n", debugstr_variant(PostData));
    }

    if(post_array) {
        LONG elem_max;
        SafeArrayAccessData(post_array, (void**)&post_data);
        SafeArrayGetUBound(post_array, 1, &elem_max);
        post_data_len = (elem_max+1) * SafeArrayGetElemsize(post_array);
    }

    if(Headers && V_VT(Headers) == VT_BSTR) {
        headers = V_BSTR(Headers);
        TRACE("Headers: %s\n", debugstr_w(headers));
    }

    set_doc_state(This, READYSTATE_LOADING);
    This->ready_state = READYSTATE_LOADING;

    if(This->doc_navigate) {
        WCHAR new_url[INTERNET_MAX_URL_LENGTH];

        if(PathIsURLW(url)) {
            new_url[0] = 0;
        }else {
            DWORD size;

            size = sizeof(new_url)/sizeof(WCHAR);
            hres = UrlApplySchemeW(url, new_url, &size,
                    URL_APPLY_GUESSSCHEME | URL_APPLY_GUESSFILE | URL_APPLY_DEFAULT);
            if(FAILED(hres)) {
                WARN("UrlApplyScheme failed: %08x\n", hres);
                new_url[0] = 0;
            }
        }

        hres = async_doc_navigate(This, *new_url ? new_url : url, headers, post_data,
                post_data_len, TRUE);
    }else {
        task_navigate_bsc_t *task;

        task = heap_alloc(sizeof(*task));
        task->bsc = create_callback(This, url, post_data, post_data_len, headers);
        push_dochost_task(This, &task->header, navigate_bsc_proc, navigate_bsc_task_destr, This->url == NULL);
    }

    if(post_data)
        SafeArrayUnaccessData(post_array);

    return hres;
}
Esempio n. 9
0
/* Extract all the files from a 7-zip archive to the specified location, with
 * callbacks. "file" is the path to the file to unpack, "base" is the location
 * to extract to, "before_entry_callback" is a function to call right before
 * each entry is unpacked, and "create_callback" is a function to call right
 * after each entry has been unpacked. Both callback functions' arguments are as
 * follows: the path (relative to base) of the entry, and an int that is nonzero
 * if the entry is a directory.
 */
int un7z
 (const char* file,
  const char* base,
  int (*before_entry_callback)(const char*, int),
  void (*create_callback)(const char*, int))
{
	// Create and fill out our reader object
	FileInStream instream;
	instream.sz_stream.Read = SzFileReadImp;
	instream.sz_stream.Seek = SzFileSeekImp;
	instream.filep = fopen(file, "rb");
	if (!instream.filep)
	{
		archive_seterror("failed to open file '%s' for reading", file);
		return -1;
	}
	// Close the FILE* when we leave this scope
	RefType< FILE >::Ref fcloser(instream.filep, fclose);

	CrcGenerateTable();

	CArchiveDatabaseEx db;
	SzArDbExInit(&db);
	// Free up the database when we leave this scope
	RefType< CArchiveDatabaseEx >::Ref db_deleter(&db, SzArDbExDeleter);

	// Set up 7-zip's memory allocation scheme (uses the default allocators)
	ISzAlloc allocImp, allocTempImp;
	allocImp.Alloc = SzAlloc;
	allocImp.Free = SzFree;
	allocTempImp.Alloc = SzAllocTemp;
	allocTempImp.Free = SzFreeTemp;

	// Open the archive
	if (SzArchiveOpen(&instream.sz_stream, &db, &allocImp, &allocTempImp)
	 != SZ_OK)
	{
		archive_seterror("7zlib couldn't open '%s' as a 7z archive", file);
		return -1;
	}

	// Update progress total
	num_files_in_cur_op = db.Database.NumFiles;

	// Set up 7-zip's "cache" variables
	UInt32 blockIndex = 0xFFFFFFFF;
	Byte *outBuffer = 0;
	size_t outBufferSize = 0;
	// Delete the buffer when we leave this scope
	RefType< Byte >::Ref outbuf_deleter(outBuffer, OutBufferDeleter);

	// Iterate and extract entries
	for (unsigned i = 0; i < db.Database.NumFiles; i++)
	{
		// Update progress
		cur_file_in_op_index = i;

		CFileItem* cur_file = &db.Database.Files[i];
		
		// Call before-extraction callback
		if (before_entry_callback)
		{
			int cbres = before_entry_callback(cur_file->Name, cur_file->IsDirectory);
			if (cbres != 0)
			{
				archive_seterror("7zlib failed to unzip '%s': cancelled from "
				 "callback", cur_file->Name);
				return cbres;
			}
		}

		// Get the full path to output
		std::string out_path = std::string(base) + "/" + cur_file->Name;

		// If entry is a directory, merely create the directory
		if (cur_file->IsDirectory)
		{
			if (!makedir(base, cur_file->Name))
			{
				archive_seterror("couldn't create directory '%s'",
				 out_path.c_str());
				return -1;
			}
		}
		// If entry is a file, extract it
		else
		{
			size_t offset, outSizeProcessed;
			// 7-zip seems to encourage getting the whole file in one blow
			SZ_RESULT res = SzExtract(&instream.sz_stream, &db, i, &blockIndex,
			 &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp,
			 &allocTempImp);
			if (res == SZE_CRC_ERROR)
			{
				archive_seterror("bad CRC for file '%s' in '%s'",
				 cur_file->Name, file);
				return -1;
			}
			else if (res != SZ_OK)
			{
				archive_seterror("7zlib failed to unpack file '%s' in '%s'",
				 cur_file->Name, file);
				return -1;
			}

			bool was_created = false;
			// If the output file already exists, make sure we can write over it
			if (chmod(out_path.c_str(), _S_IREAD|_S_IWRITE) != 0)
				was_created = true;

			// Open the output file for writing
			FILE* outfile = fopen(out_path.c_str(), "wb");
			if (!outfile)
			{
				// Couldn't open it -- make sure its parent directory exists
				size_t p = std::string(cur_file->Name).find_last_of("/\\", std::string::npos);
				if (p != std::string::npos)
				{
					makedir(base, std::string(cur_file->Name).substr(0, p).c_str());
					outfile = fopen(out_path.c_str(), "wb");
				}
			}
			if (!outfile)
			{
				// Still couldn't open it; error out
				archive_seterror("couldn't open '%s' for writing",
				 out_path.c_str());
				return -1;
			}

			// Write out the whole file and then close it
			int written = fwrite(outBuffer + offset, 1, outSizeProcessed,
			 outfile);
			fclose(outfile);
			if (written <= 0
			 || static_cast< size_t >(written) != outSizeProcessed)
			{
				// At this point we have an empty output file; remove it
				remove(out_path.c_str());
				archive_seterror("failed to write %d bytes to '%s'",
				 outSizeProcessed, out_path.c_str());
				return -1;
			}
		}

		// Set stored attributes
		if (cur_file->AreAttributesDefined)
			SetFileAttributes(out_path.c_str(), cur_file->Attributes);

		// Call after-creation callback
		create_callback(cur_file->Name, cur_file->IsDirectory ? 1 : 0);
	}

	return 0;
}
Esempio n. 10
0
/**
 * Creates a control from the given XMLNode as a child of the given
 * parent.
 *
 * @param form the SubForm object
 * @param LookUpTable The parent CallBackTable
 * @param node The XMLNode that represents the control
 */
static Window *
LoadChild(SubForm &form, ContainerWindow &parent,
          const CallBackTableEntry *lookup_table, XMLNode node,
          int bottom_most,
          WindowStyle style)
{
  Window *window = NULL;

  // Determine name, coordinates, width, height
  // and caption of the control
  const TCHAR* name = GetName(node);
  const TCHAR* caption = GetCaption(node);
  PixelRect rc = parent.get_client_rect();
  ControlPosition pos = GetPosition(node, rc, bottom_most);
  if (!pos.no_scaling)
    pos.x = ScaleWidth(pos.x);

  ControlSize size = GetSize(node, rc, pos);
  if (!size.no_scaling)
    size.cx = ScaleWidth(size.cx);

  if (!StringToIntDflt(node.getAttribute(_T("Visible")), 1))
    style.Hide();

  if (StringToIntDflt(node.getAttribute(_T("Border")), 0))
    style.Border();

  rc.left = pos.x;
  rc.top = pos.y;
  rc.right = rc.left + size.cx;
  rc.bottom = rc.top + size.cy;

  bool expert = (StringToIntDflt(node.getAttribute(_T("Expert")), 0) == 1);

  // PropertyControl (WndProperty)
  if (StringIsEqual(node.getName(), _T("Edit"))) {
    // Determine the width of the caption field
    int caption_width = StringToIntDflt(node.getAttribute(_T("CaptionWidth")), 0);

    if (Layout::ScaleSupported())
      caption_width = Layout::Scale(caption_width);

    caption_width = ScaleWidth(caption_width);

    // Determine whether the control is multiline or readonly
    bool multi_line = StringToIntDflt(node.getAttribute(_T("MultiLine")), 0);
    bool read_only = StringToIntDflt(node.getAttribute(_T("ReadOnly")), 0);

    // Load the event callback properties
    WndProperty::DataChangeCallback_t data_notify_callback =
      (WndProperty::DataChangeCallback_t)
      GetCallBack(lookup_table, node, _T("OnDataNotify"));

    WindowControl::HelpCallback help_callback =
      (WindowControl::HelpCallback)
      GetCallBack(lookup_table, node, _T("OnHelp"));

    // Create the Property Control
    style.ControlParent();

    EditWindowStyle edit_style;
    edit_style.vertical_center();
    if (read_only)
      edit_style.read_only();
    else
      edit_style.TabStop();

    if (IsEmbedded() || Layout::scale_1024 < 2048)
      /* sunken edge doesn't fit well on the tiny screen of an
         embedded device */
      edit_style.Border();
    else
      edit_style.SunkenEdge();

    if (multi_line) {
      edit_style.multiline();
      edit_style.VerticalScroll();
    }

    WndProperty *property;
    window = property = new WndProperty(parent, *xml_dialog_look, caption, rc,
                                        caption_width, style, edit_style,
                                        data_notify_callback);

    // Set the help function event callback
    property->SetOnHelpCallback(help_callback);

    // Load the help text
    property->SetHelpText(StringToStringDflt(node.getAttribute(_T("Help")),
                                             NULL));

    // If the control has (at least) one DataField child control
    const XMLNode *data_field_node = node.getChildNode(_T("DataField"));
    if (data_field_node != NULL) {
      // -> Load the first DataField control
      DataField *data_field =
        LoadDataField(*data_field_node, lookup_table);

      if (data_field != NULL)
        // Tell the Property control about the DataField control
        property->SetDataField(data_field);
    }

  } else if (StringIsEqual(node.getName(), _T("TextEdit"))) {
    // Determine whether the control is multiline or readonly
    bool multi_line = StringToIntDflt(node.getAttribute(_T("MultiLine")), 0);
    bool read_only = StringToIntDflt(node.getAttribute(_T("ReadOnly")), 0);

    EditWindowStyle edit_style(style);
    if (read_only)
      edit_style.read_only();
    else
      edit_style.TabStop();

    if (IsEmbedded() || Layout::scale_1024 < 2048)
      /* sunken edge doesn't fit well on the tiny screen of an
         embedded device */
      edit_style.Border();
    else
      edit_style.SunkenEdge();

    if (multi_line) {
      edit_style.multiline();
      edit_style.VerticalScroll();
    }

    EditWindow *edit;
    window = edit = new EditWindow();
    edit->set(parent, pos.x, pos.y, size.cx, size.cy, edit_style);
    edit->InstallWndProc();
    edit->set_font(*xml_dialog_look->text_font);

  // ButtonControl (WndButton)
  } else if (StringIsEqual(node.getName(), _T("Button"))) {
    // Determine ClickCallback function
    WndButton::ClickNotifyCallback click_callback =
      (WndButton::ClickNotifyCallback)
      GetCallBack(lookup_table, node, _T("OnClick"));

    // Create the ButtonControl

    ButtonWindowStyle button_style(style);
    button_style.TabStop();
    button_style.multiline();

    window = new WndButton(parent, *xml_dialog_look, caption,
                           rc,
                           button_style, click_callback);

  } else if (StringIsEqual(node.getName(), _T("CheckBox"))) {
    // Determine click_callback function
    CheckBoxControl::ClickNotifyCallback click_callback =
      (CheckBoxControl::ClickNotifyCallback)
      GetCallBack(lookup_table, node, _T("OnClick"));

    // Create the CheckBoxControl

    style.TabStop();

    window = new CheckBoxControl(parent, *xml_dialog_look, caption,
                                 rc,
                                 style, click_callback);

  // SymbolButtonControl (WndSymbolButton) not used yet
  } else if (StringIsEqual(node.getName(), _T("SymbolButton"))) {
    // Determine ClickCallback function
    WndButton::ClickNotifyCallback click_callback =
      (WndButton::ClickNotifyCallback)
      GetCallBack(lookup_table, node, _T("OnClick"));

    // Create the SymbolButtonControl

    style.TabStop();

    window = new WndSymbolButton(parent, *xml_dialog_look, caption,
                                 rc,
                                 style, click_callback);

  // PanelControl (WndPanel)
  } else if (StringIsEqual(node.getName(), _T("Panel"))) {
    // Create the PanelControl

    style.ControlParent();

    PanelControl *frame = new PanelControl(parent, *xml_dialog_look,
                                           rc,
                                           style);

    window = frame;

    // Load children controls from the XMLNode
    LoadChildrenFromXML(form, *frame,
                        lookup_table, &node);

  // KeyboardControl
  } else if (StringIsEqual(node.getName(), _T("Keyboard"))) {
    KeyboardControl::OnCharacterCallback_t character_callback =
      (KeyboardControl::OnCharacterCallback_t)
      GetCallBack(lookup_table, node, _T("OnCharacter"));

    // Create the KeyboardControl
    KeyboardControl *kb =
      new KeyboardControl(parent, *xml_dialog_look,
                          pos.x, pos.y, size.cx, size.cy,
                          character_callback, style);

    window = kb;
  // DrawControl (WndOwnerDrawFrame)
  } else if (StringIsEqual(node.getName(), _T("Canvas"))) {
    // Determine DrawCallback function
    WndOwnerDrawFrame::OnPaintCallback_t paint_callback =
      (WndOwnerDrawFrame::OnPaintCallback_t)
      GetCallBack(lookup_table, node, _T("OnPaint"));

    // Create the DrawControl
    WndOwnerDrawFrame* canvas =
      new WndOwnerDrawFrame(parent, pos.x, pos.y, size.cx, size.cy,
                            style, paint_callback);

    window = canvas;

  // FrameControl (WndFrame)
  } else if (StringIsEqual(node.getName(), _T("Label"))){
    // Create the FrameControl
    WndFrame* frame = new WndFrame(parent, *xml_dialog_look,
                                   pos.x, pos.y, size.cx, size.cy,
                                   style);

    // Set the caption
    frame->SetCaption(caption);
    // Set caption color
    Color color;
    if (StringToColor(node.getAttribute(_T("CaptionColor")), color))
      frame->SetCaptionColor(color);

    window = frame;

  // ListBoxControl (WndListFrame)
  } else if (StringIsEqual(node.getName(), _T("List"))){
    // Determine ItemHeight of the list items
    UPixelScalar item_height =
      Layout::Scale(StringToIntDflt(node.getAttribute(_T("ItemHeight")), 18));

    // Create the ListBoxControl

    style.TabStop();

    if (IsEmbedded() || Layout::scale_1024 < 2048)
      /* sunken edge doesn't fit well on the tiny screen of an
         embedded device */
      style.Border();
    else
      style.SunkenEdge();

    window = new WndListFrame(parent, *xml_dialog_look,
                              pos.x, pos.y, size.cx, size.cy,
                              style,
                              item_height);

  // TabControl (Tabbed)
  } else if (StringIsEqual(node.getName(), _T("Tabbed"))) {
    // Create the TabControl

    style.ControlParent();

    TabbedControl *tabbed = new TabbedControl(parent,
                                              pos.x, pos.y, size.cx, size.cy,
                                              style);

    window = tabbed;

    for (auto i = node.begin(), end = node.end(); i != end; ++i) {
      // Load each child control from the child nodes
      Window *child = LoadChild(form, *tabbed,
                                lookup_table,
                                *i);
      if (child != NULL)
        tabbed->AddClient(child);
    }
  // TabBarControl (TabBar)
  } else if (StringIsEqual(node.getName(), _T("TabBar"))) {
    // Create the TabBarControl

    bool flip_orientation = false;
    if ( (Layout::landscape && StringToIntDflt(node.getAttribute(_T("Horizontal")), 0)) ||
         (!Layout::landscape && StringToIntDflt(node.getAttribute(_T("Vertical")), 0) ) )
      flip_orientation = true;

    style.ControlParent();
    TabBarControl *tabbar = new TabBarControl(parent, *xml_dialog_look,
                                              pos.x, pos.y, size.cx, size.cy,
                                              style, flip_orientation);
    window = tabbar;

    // TabMenuControl (TabMenu)
  } else if (StringIsEqual(node.getName(), _T("TabMenu"))) {
    // Create the TabMenuControl

    style.ControlParent();
    TabMenuControl *tabmenu = new TabMenuControl(parent,
                                                 /* XXX this cast is
                                                    an ugly hack!
                                                    Please rewrite: */
                                                 (WndForm &)form,
                                                 *xml_dialog_look, caption,
                                                 pos.x, pos.y, size.cx, size.cy,
                                                 style);
    window = tabmenu;

  } else if (StringIsEqual(node.getName(), _T("Custom"))) {
    // Create a custom Window object with a callback
    CreateWindowCallback_t create_callback =
        (CreateWindowCallback_t)GetCallBack(lookup_table, node, _T("OnCreate"));
    if (create_callback == NULL)
      return NULL;

    window = create_callback(parent, pos.x, pos.y, size.cx, size.cy, style);
  } else if (StringIsEqual(node.getName(), _T("Widget"))) {
    style.ControlParent();
    DockWindow *dock = new DockWindow();
    dock->set(parent, rc, style);
    window = dock;
  }

  if (window != NULL) {
    if (!StringIsEmpty(name))
      form.AddNamed(name, window);

    if (expert)
      form.AddExpert(window);

    form.AddDestruct(window);
  }

  return window;
}