📄 kwqkhtmlpart.cpp
字号:
if (i != 0) { pattern.append("|"); } // Search for word boundaries only if label starts/ends with "word characters". // If we always searched for word boundaries, this wouldn't work for languages // such as Japanese. if (startsWithWordChar) { pattern.append("\\b"); } pattern.append(label); if (endsWithWordChar) { pattern.append("\\b"); } } pattern.append(")"); result = new QRegExp(pattern, false); } // add regexp to the cache, making sure it is at the front for LRU ordering if (cacheHit != 0) { if (cacheHit != NSNotFound) { // remove from old spot [regExpLabels removeObjectAtIndex:cacheHit]; regExps.remove(cacheHit); } // add to start [regExpLabels insertObject:labels atIndex:0]; regExps.insert(0, result); // trim if too big if ([regExpLabels count] > regExpCacheSize) { [regExpLabels removeObjectAtIndex:regExpCacheSize]; QRegExp *last = regExps.last(); regExps.removeLast(); delete last; } } return result;}NSString *KWQKHTMLPart::searchForLabelsAboveCell(QRegExp *regExp, HTMLTableCellElementImpl *cell){ RenderTableCell *cellRenderer = static_cast<RenderTableCell *>(cell->renderer()); RenderTableCell *cellAboveRenderer = cellRenderer->table()->cellAbove(cellRenderer); if (cellAboveRenderer) { HTMLTableCellElementImpl *aboveCell = static_cast<HTMLTableCellElementImpl *>(cellAboveRenderer->element()); if (aboveCell) { // search within the above cell we found for a match for (NodeImpl *n = aboveCell->firstChild(); n; n = n->traverseNextNode(aboveCell)) { if (idFromNode(n) == ID_TEXT && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) { // For each text chunk, run the regexp QString nodeString = n->nodeValue().string(); int pos = regExp->searchRev(nodeString); if (pos >= 0) { return nodeString.mid(pos, regExp->matchedLength()).getNSString(); } } } } } // Any reason in practice to search all cells in that are above cell? return nil;}NSString *KWQKHTMLPart::searchForLabelsBeforeElement(NSArray *labels, ElementImpl *element){ QRegExp *regExp = regExpForLabels(labels); // We stop searching after we've seen this many chars const unsigned int charsSearchedThreshold = 500; // This is the absolute max we search. We allow a little more slop than // charsSearchedThreshold, to make it more likely that we'll search whole nodes. const unsigned int maxCharsSearched = 600; // If the starting element is within a table, the cell that contains it HTMLTableCellElementImpl *startingTableCell = 0; bool searchedCellAbove = false; // walk backwards in the node tree, until another element, or form, or end of tree int unsigned lengthSearched = 0; NodeImpl *n; for (n = element->traversePreviousNode(); n && lengthSearched < charsSearchedThreshold; n = n->traversePreviousNode()) { NodeImpl::Id nodeID = idFromNode(n); if (nodeID == ID_FORM || (n->isHTMLElement() && static_cast<HTMLElementImpl *>(n)->isGenericFormElement())) { // We hit another form element or the start of the form - bail out break; } else if (nodeID == ID_TD && !startingTableCell) { startingTableCell = static_cast<HTMLTableCellElementImpl *>(n); } else if (nodeID == ID_TR && startingTableCell) { NSString *result = searchForLabelsAboveCell(regExp, startingTableCell); if (result) { return result; } searchedCellAbove = true; } else if (nodeID == ID_TEXT && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) { // For each text chunk, run the regexp QString nodeString = n->nodeValue().string(); // add 100 for slop, to make it more likely that we'll search whole nodes if (lengthSearched + nodeString.length() > maxCharsSearched) { nodeString = nodeString.right(charsSearchedThreshold - lengthSearched); } int pos = regExp->searchRev(nodeString); if (pos >= 0) { return nodeString.mid(pos, regExp->matchedLength()).getNSString(); } else { lengthSearched += nodeString.length(); } } } // If we started in a cell, but bailed because we found the start of the form or the // previous element, we still might need to search the row above us for a label. if (startingTableCell && !searchedCellAbove) { return searchForLabelsAboveCell(regExp, startingTableCell); } else { return nil; }}NSString *KWQKHTMLPart::matchLabelsAgainstElement(NSArray *labels, ElementImpl *element){ QString name = element->getAttribute(ATTR_NAME).string(); // Make numbers and _'s in field names behave like word boundaries, e.g., "address2" name.replace(QRegExp("[[:digit:]]"), " "); name.replace('_', ' '); QRegExp *regExp = regExpForLabels(labels); // Use the largest match we can find in the whole name string int pos; int length; int bestPos = -1; int bestLength = -1; int start = 0; do { pos = regExp->search(name, start); if (pos != -1) { length = regExp->matchedLength(); if (length >= bestLength) { bestPos = pos; bestLength = length; } start = pos+1; } } while (pos != -1); if (bestPos != -1) { return name.mid(bestPos, bestLength).getNSString(); } else { return nil; }}#endif // if 0// Search from the end of the currently selected location if we are first responder, or from// the beginning of the document if nothing is selected or we're not first responder.bool KWQKHTMLPart::findString(const QString& target, bool forward, bool caseFlag, bool wrapFlag){ if (target.isEmpty()) { return false; } // Start on the correct edge of the selection, search to edge of document. Range searchRange(xmlDocImpl()); searchRange.selectNodeContents(xmlDocImpl()); if (selectionStart()) { if (forward) { searchRange.setStart(selectionEnd(), selectionEndOffset()); } else { searchRange.setEnd(selectionStart(), selectionStartOffset()); } } // Do the search once, then do it a second time to handle wrapped search. // Searches some or all of document twice in the failure case, but that's probably OK. Range resultRange = findPlainText(searchRange, target, forward, caseFlag); if (resultRange.collapsed() && wrapFlag) { searchRange.selectNodeContents(xmlDocImpl()); resultRange = findPlainText(searchRange, target, forward, caseFlag); // If we got back to the same place we started, that doesn't count as success. if (resultRange == selection().toRange()) { return false; } } if (resultRange.collapsed()) { return false; } setSelection(resultRange); jumpToSelection(); return true;}void KWQKHTMLPart::clearRecordedFormValues(){ if (_formValuesAboutToBeSubmitted) { g_hash_table_destroy(_formValuesAboutToBeSubmitted); _formValuesAboutToBeSubmitted = 0; _formAboutToBeSubmitted = 0; }}extern "C" {void formValuesAboutToBeSubmitted_value_key_destroy(gpointer data){ gchar *c = static_cast<gchar *>(data); g_free(c);}}void KWQKHTMLPart::recordFormValue(const QString &name, const QString &value, DOM::HTMLFormElementImpl *element){ if (!_formValuesAboutToBeSubmitted){ _formValuesAboutToBeSubmitted = g_hash_table_new_full(g_str_hash, g_str_equal, formValuesAboutToBeSubmitted_value_key_destroy, formValuesAboutToBeSubmitted_value_key_destroy); _formAboutToBeSubmitted = 0; // element; <-- wrap that with DOM api } else { //ASSERT(_formAboutToBeSubmitted->impl() == element); } g_hash_table_insert(_formValuesAboutToBeSubmitted, g_strdup(name.utf8()), g_strdup(value.utf8()));}void KWQKHTMLPart::submitForm(const KURL &url, const URLArgs &args){ // The form multi-submit logic here is only right when we are submitting a form that affects this frame. // Eventually when we find a better fix we can remove this altogether. // FIXME: utf8? -- psalmi WebCoreBridge *target = args.frameName.isEmpty() ? _bridge : _bridge->findFrameNamed(args.frameName.utf8()); if (!target) target = _bridge; KHTMLPart *targetPart = target->part(); bool willReplaceThisFrame = false; for (KHTMLPart *p = this; p; p = p->parentPart()) { if (p == targetPart) { willReplaceThisFrame = true; break; } } if (willReplaceThisFrame) { // We do not want to submit more than one form from the same page, // nor do we want to submit a single form more than once. // This flag prevents these from happening. // Note that the flag is reset in setView() // since this part may get reused if it is pulled from the b/f cache. if (_submittedFormURL == url) { return; } _submittedFormURL = url; } if (!args.doPost()) { // FIXME: utf8? -- psalmi _bridge->loadURL(url.url().utf8(), _bridge->referrer(), args.reload, false, args.frameName.utf8(), _currentEvent, _formAboutToBeSubmitted, _formValuesAboutToBeSubmitted); } else { ASSERT(args.contentType().startsWith("Content-Type: ")); const int size = args.postData.size(); GByteArray * postData = g_byte_array_sized_new(size); g_byte_array_append(postData, reinterpret_cast<guint8 *>(g_strdup(args.postData.data())), size); _bridge->postWithURL(url.url().utf8(), _bridge->referrer(), args.frameName.utf8(), postData, args.contentType().mid(14).utf8(), _currentEvent, _formAboutToBeSubmitted, _formValuesAboutToBeSubmitted); g_byte_array_free(postData, true); } clearRecordedFormValues(); }void KWQKHTMLPart::setEncoding(const QString &name, bool userChosen){ if (!d->m_workingURL.isEmpty()) { receivedFirstData(); } d->m_encoding = name; d->m_haveEncoding = userChosen;}void KWQKHTMLPart::addData(const char *bytes, int length){ ASSERT(d->m_workingURL.isEmpty()); ASSERT(d->m_doc); ASSERT(d->m_doc->parsing()); write(bytes, length);}void KHTMLPart::frameDetached(){ KWQ(this)->bridge()->frameDetached(); // FIXME: There may be a better place to do this that works for KHTML too. FrameList& parentFrames = parentPart()->d->m_frames; FrameIt end = parentFrames.end(); for (FrameIt it = parentFrames.begin(); it != end; ++it) { if ((*it).m_part == this) { parentFrames.remove(it); deref(); break; } }}void KWQKHTMLPart::urlSelected(const KURL &url, int button, int state, const URLArgs &args){ _bridge->loadURL(url.url().utf8(), _bridge->referrer(), args.reload, false, args.frameName.utf8(), _currentEvent, 0, 0);}class KWQPluginPart : public ReadOnlyPart{ virtual bool openURL(const KURL &) { return true; } virtual bool closeURL() { return true; }public:};KParts::ReadOnlyPart *KWQKHTMLPart::createPart(const khtml::ChildFrame &child, const KURL &url, const QString &mimeType){ KParts::ReadOnlyPart *part; bool needFrame = _bridge->frameRequiredForMIMEType(mimeType.utf8(), url.url().utf8()); if (child.m_type == ChildFrame::Object && !needFrame) { KWQPluginPart *newPart = new KWQPluginPart; GList* params = 0; for (uint i = 0; i < child.m_params.count(); i++){ QString s = child.m_params[i]; params = g_list_append(params, g_strdup(s.utf8())); } newPart->setWidget(new QWidget( _bridge->widgetForPluginWithURL(url.url().utf8(), params, d->m_doc->baseURL().utf8(), child.m_args.serviceType.utf8()))); part = newPart; GList* iter = g_list_first(params); while (iter) { g_free(iter->data); iter = g_list_next(iter); } g_list_free(params); } else { LOG(Frames, "name %s", child.m_name.ascii()); bool allowsScrolling = true; int marginWidth = -1; int marginHeight = -1; if (child.m_type != ChildFrame::Object) { DOM::HTMLFrameElementImpl *o = static_cast<DOM::HTMLFrameElementImpl *>(child.m_frame->element()); allowsScrolling = o->scrollingMode() != QScrollView::AlwaysOff; marginWidth = o->getMarginWidth(); marginHeight = o->getMarginHeight(); } WebCoreBridge *childBridge = _bridge->createChildFrameNamed(child.m_name.utf8(), url.url().utf8(), child.m_frame, allowsScrolling, marginWidth, marginHeight); // This call needs to return an object with a ref, since the caller will expect to own it. // childBridge owns the only ref so far. childBridge->part()->ref(); part = childBridge->part(); } return part;}void KWQKHTMLPart::setView(KHTMLView *view){ // Detach the document now, so any onUnload handlers get run - if // we wait until the view is destroyed, then things won't be // hooked up enough for some JavaScript calls to work. if (d->m_doc && view == NULL) { d->m_doc->detach(); } if (view) { view->ref(); } if (d->m_view) { d->m_view->deref(); } d->m_view = view;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -