docs: public synchronized String listHtml() {
  
          // check if progress should be set in the thread
          CmsProgressThread thread = null;
          int progressOffset = 0;
          if (Thread.currentThread() instanceof CmsProgressThread) {
              thread = (CmsProgressThread)Thread.currentThread();
              progressOffset = thread.getProgress();
          }
  
          // this block has to be executed before calling htmlBegin()
          if (isPrintable()) {
              m_visibleItems = new ArrayList<CmsListItem>(getContent());
          } else {
              m_visibleItems = new ArrayList<CmsListItem>(getCurrentPageItems());
          }
  
          StringBuffer html = new StringBuffer(5120);
          html.append(htmlBegin());
          if (!isPrintable()) {
              html.append(htmlTitle());
              html.append(htmlToolBar());
          } else {
              html.append("<style type='text/css'>\n");
              html.append("td.listdetailitem, \n");
              html.append(".linkdisabled {\n");
              html.append("\tcolor: black;\n");
              html.append("}\n");
              html.append(".list th {\n");
              html.append("\tborder: 1px solid black;\n");
              html.append("}\n");
              html.append(".list {\n");
              html.append("\tborder: 1px solid black;\n");
              html.append("}\n");
              html.append("</style>");
          }
          // avoiding the layout problem where, if some table cells contain a lot of text,
          // the right side of the table is cut off and can not be reached using the scroll bar.
          html.append("<!--[if IE 7]>");
          html.append("<style type='text/css'>");
          html.append("table.list * { word-wrap: break-word !important; white-space: normal !important; }");
          html.append("table.list { table-layout: fixed; }");
          html.append("</style>");
          html.append("<![endif]-->");
  
          html.append("<table width='100%' cellpadding='1' cellspacing='0' class='list'>\n");
          html.append(m_metadata.htmlHeader(this));
          if (m_visibleItems.isEmpty()) {
              html.append(m_metadata.htmlEmptyTable());
          } else {
              Iterator<CmsListItem> itItems = m_visibleItems.iterator();
              boolean odd = true;
              int count = 0;
              while (itItems.hasNext()) {
  
                  // set progress in thread
                  count++;
                  if (thread != null) {
  
                      if (thread.isInterrupted()) {
                          throw new CmsIllegalStateException(
                              org.opencms.workplace.commons.Messages.get().container(
                                  org.opencms.workplace.commons.Messages.ERR_PROGRESS_INTERRUPTED_0));
                      }
                      thread.setProgress(((count * (100 - progressOffset)) / m_visibleItems.size()) + progressOffset);
                      thread.setDescription(
                          org.opencms.workplace.commons.Messages.get().getBundle(thread.getLocale()).key(
                              org.opencms.workplace.commons.Messages.GUI_PROGRESS_PUBLISH_STEP4_2,
                              new Integer(count),
                              new Integer(m_visibleItems.size())));
                  }
  
                  CmsListItem item = itItems.next();
                  html.append(m_metadata.htmlItem(item, odd, isPrintable()));
                  odd = !odd;
              }
          }
  
          html.append("</table>\n");
          if (!isPrintable()) {
              html.append(htmlPagingBar());
          }
          html.append(htmlEnd());
          return getWp().resolveMacros(html.toString());
      }