Exemplo n.º 1
0
//add a task to runTimeStorage
//no duplicate task is allowed.
void RunTimeStorage::add(Task task) {
	if (isDuplicate(task)) {
		throw DUPLICATE_TASK_EXCEPTION(); 
	}
	_tasks.push_back(task);
	return;
}
Exemplo n.º 2
0
int main(){
    int i, numUnique = 0, b, a;
    short uniqueNum[10000][30] = {{0}};
    short basePrimeFactor[30] = {0}, curr[30] = {0};

    genPrimes();

    for (a = 2; a <= 100; a++){
        memset(basePrimeFactor, 0, sizeof(short)*30); 
        factorize(a, basePrimeFactor);

        for (b = 2; b <= 100; b++){
            for (i = 0; i < 30; i++){
                curr[i] = basePrimeFactor[i]*b;
            }
            if (!isDuplicate(curr, uniqueNum, numUnique)){
                memcpy(uniqueNum[numUnique], curr, sizeof(short)*30);
                numUnique++;
            }
        }
    }

    printf("%d\n", numUnique);

    return 0;
}
Exemplo n.º 3
0
/*
 * this should be part of a child class, but I'm lazy right now
 */
void TreeModel::xBasicIncludes(QString &text)
{
    QString inc, cap, s;
    QStringList st = text.split('\n');
    QRegExp rx("(include) ([^\n]*)");
    rx.setCaseSensitivity(Qt::CaseInsensitive);

    int len = st.length();
    for(int n = 0; n < len; n++)
    {
        s = st.at(n);
        int gotit = rx.indexIn(s);
        if(gotit > -1) {
            QList<QVariant> clist;
            inc = rx.cap(1);
            cap = rx.cap(2);
            if(cap != "" && cap.indexOf("\"") > -1) {
                QStringList caps = cap.split("\"");
                cap = caps.at(1);
                cap = cap.trimmed();
                clist << cap;
                if(!isDuplicate(rootItem, cap))
                    rootItem->appendChild(new TreeItem(clist, rootItem));
            }
        }
    }
}
Exemplo n.º 4
0
UtlBoolean
SipLineList::isDuplicate( SipLine *line )
{
    // Changed this to call common code
    Url lineIdentityUrl = line->getIdentity();
    return isDuplicate( lineIdentityUrl );
}
Exemplo n.º 5
0
void Receiver::received(Message& message)
{
    if (!(skipDups && isDuplicate(message))) {
        bool eos = message.getData() == EOS;
        if (!eos) std::cout << message.getData() << std::endl;
        if (eos || ++processed == count) subscription.cancel();
    }
}
Exemplo n.º 6
0
void Widget::processCookies(Cookies cookies) {
  if (isDuplicate(cookies))
    return;
  cookiesMgr_.push_back(cookies);
  CookieTreeWidgetItem* item = new CookieTreeWidgetItem(ui->twCookie, cookies);
  item->setFlags(item->flags() | Qt::ItemIsEditable);
  item->setText(0, cookies.time.toString("hh:mm:ss"));
  item->setText(1, cookies.ip);
  item->setText(2, cookies.url);
}
Exemplo n.º 7
0
void OpenEditorsModel::makeOriginal(IEditor *duplicate)
{
    Q_ASSERT(duplicate && isDuplicate(duplicate));
    IEditor *original = originalForDuplicate(duplicate);
    Q_ASSERT(original);
    int i = findEditor(original);
    m_editors[i].editor = duplicate;
    m_duplicateEditors.removeOne(duplicate);
    m_duplicateEditors.append(original);
    disconnect(original, SIGNAL(changed()), this, SLOT(itemChanged()));
    connect(duplicate, SIGNAL(changed()), this, SLOT(itemChanged()));
}
Exemplo n.º 8
0
/*
 * this should be part of a child class, but I'm lazy right now
 */
void TreeModel::xBasicIncludes(QString &filePath, QString &incPath, QString &separator, QString &text, bool root)
{
    QString inc, cap, s;
    QStringList st = text.split('\n');
    QRegExp rx("(include) ([^\n]*)");

    rx.setCaseSensitivity(Qt::CaseInsensitive);

    int len = st.length();
    for(int n = 0; n < len; n++)
    {
        s = st.at(n);
        int gotit = rx.indexIn(s);
        if(gotit > -1) {
            QList<QVariant> clist;
            inc = rx.cap(1);
            cap = rx.cap(2);
            if(cap != "" && cap.indexOf("\"") > -1) {
                QStringList caps = cap.split("\"");
                cap = caps.at(1);
                cap = cap.trimmed();
                clist << cap;
                if(!isDuplicate(rootItem, cap))
                    rootItem->appendChild(new TreeItem(clist, rootItem));
            }

            QString newPath = filePath.mid(0,(filePath.lastIndexOf(separator)+1))+cap;
            QString newInc = incPath+cap;
            if(QFile::exists(newPath) == true)
            {
                QString filename = newPath;
                QFile myfile(filename);
                if (myfile.open(QFile::ReadOnly | QFile::Text))
                {
                    text = myfile.readAll();
                    myfile.close();
                    xBasicIncludes(filename, incPath, separator, text);
                }
            }
            else if(QFile::exists(newInc) == true)
            {
                QString filename = newInc;
                QFile myfile(filename);
                if (myfile.open(QFile::ReadOnly | QFile::Text))
                {
                    text = myfile.readAll();
                    myfile.close();
                    xBasicIncludes(filename, incPath, separator, text);
                }
            }
        }
    }
}
Exemplo n.º 9
0
void generateDatabase(registration (&database)[NUM_REGISTRATIONS])
{
  int regCount = 0;
  while (regCount < NUM_REGISTRATIONS)
  {
    registration reg = generateRegistration();

    if (!isDuplicate(regCount, reg, database))
    {
      database[regCount] = reg;
      regCount++;
    }
  }
}
Exemplo n.º 10
0
// send smth to address 'addr', port 'port' 
void networkingForwardData(MacInfo_t *macInfo, uint8_t *data, uint16_t len) {
    // PRINTF("commForwardData, len=%u\n", len);
    
    switch (routePacket(macInfo)) {
    case RD_DROP:
        // PRINTF("RD_DROP\n");
        if (IS_LOCAL(macInfo)){
            INC_NETSTAT(NETSTAT_PACKETS_DROPPED_TX, EMPTY_ADDR);
        } else{
            INC_NETSTAT(NETSTAT_PACKETS_DROPPED_RX, EMPTY_ADDR);
        }
        break;

    case RD_LOCAL:
        // PRINTF("RD_LOCAL\n");
        socketInputData(macInfo, data, len);
        break;

    case RD_UNICAST:
        // PRINTF("RD_UNICAST\n");
        // force header rebuild
        macInfo->macHeaderLen = 0;
#if PLATFORM_SADMOTE
        if (!IS_LOCAL(macInfo) && isDuplicate(macInfo, data, len)) {
            PRINTF("not forwarding, duplicate...\n");
            break;
        }
#endif
        if (IS_LOCAL(macInfo)) {
            INC_NETSTAT(NETSTAT_PACKETS_SENT, macInfo->originalDst.shortAddr);
        }
        macSendEx(macInfo, data, len);
        break;

    case RD_BROADCAST:
        // PRINTF("RD_BROADCAST\n");
        if (!IS_LOCAL(macInfo)) {
            socketInputData(macInfo, data, len);
        }
        // and forward to all
        intToAddr(macInfo->originalDst, OSW_ADDR_BROADCAST);
        // force header rebuild
        macInfo->macHeaderLen = 0;
        INC_NETSTAT(NETSTAT_PACKETS_SENT, EMPTY_ADDR);
        macSendEx(macInfo, data, len);
        break;
    }
}
Exemplo n.º 11
0
void ConvexBuilder::getMesh(const ConvexResult &cr,VertexLookup vc,UintVector &indices)
{
	unsigned int *src = cr.mHullIndices;

	for (unsigned int i=0; i<cr.mHullTcount; i++)
	{
		unsigned int i1 = *src++;
		unsigned int i2 = *src++;
		unsigned int i3 = *src++;

		const float *p1 = &cr.mHullVertices[i1*3];
		const float *p2 = &cr.mHullVertices[i2*3];
		const float *p3 = &cr.mHullVertices[i3*3];

		i1 = Vl_getIndex(vc,p1);
		i2 = Vl_getIndex(vc,p2);
		i3 = Vl_getIndex(vc,p3);

#if 0
		bool duplicate = false;

		unsigned int tcount = indices.size()/3;
		for (unsigned int j=0; j<tcount; j++)
		{
			unsigned int ci1 = indices[j*3+0];
			unsigned int ci2 = indices[j*3+1];
			unsigned int ci3 = indices[j*3+2];
			if ( isDuplicate(i1,i2,i3, ci1, ci2, ci3 ) )
			{
				duplicate = true;
				break;
			}
		}

		if ( !duplicate )
		{
			indices.push_back(i1);
			indices.push_back(i2);
			indices.push_back(i3);
		}
#endif

	}
}
void getDir(std::string dir, filepath * map, std::ofstream &outfile){
  //directory pointer
  DIR *directory;//DIR: a type representing a directory stream, display a list of files and subfolders
  //dir entry pointer
  struct dirent * enter;
  struct stat buf;
  std::cout << "dir is: " << dir << std::endl;
  directory = opendir(dir.c_str());  //DIR* opendir(const char *)
  std::cout << "The directory is " << directory << std::endl;
  if (dir.at(dir.length() - 1) != '/'){
    dir = dir + "/";
  }
  if (directory != NULL){
    while ((enter = readdir(directory))){
      if (strcmp(enter->d_name, ".") != 0 && strcmp(enter->d_name, "..") != 0){
          if (lstat((dir + enter->d_name).c_str(), &buf) != -1){
	      if (S_ISDIR(buf.st_mode)) {
	          //protection mode; S_ISDIR:test for a directory
                  std::cout << "a directory!\n";
	          getDir(dir + enter->d_name, map, outfile);
               }
	       else if (S_ISREG(buf.st_mode)){//S_ISREG: test for a regular file
                  std::cout << "a file!\n";
	          std::string fnameMapped = isDuplicate(map, dir+enter->d_name);
	          if (fnameMapped != "") {
                      showInScript(outfile, dir+enter->d_name, fnameMapped);
                  }
	          else {
   	              addToMap(map, dir+enter->d_name);
	          }
               }
           }
           else {
               perror("Could not get the file information!");
           }
        }
     }
    closedir(directory);
  }
    else {
        perror("Could not open the directory!");
    }
}
Exemplo n.º 13
0
int main(int argc, char *argv[])
{
	int x, y, i, OK, startIndex;
	char name[20];
	SDL_Rect src, dest;
	unsigned char r, g, b;
	int *pixels, xx, yy, pixel;
	int colour;

	i = 0;

	if (argc != 3)
	{
		printf("Usage: %s <PNG File> <Start_Index>\n", argv[0]);

		exit(0);
	}

	atexit(cleanup);

	if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK|SDL_INIT_AUDIO) < 0)
	{
		printf("Could not initialize SDL: %s\n", SDL_GetError());

		exit(1);
	}

	screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);

	image = loadImage(argv[1]);

	i = atoi(argv[2]);

	startIndex = i;

	temp = SDL_CreateRGBSurface(SDL_HWSURFACE, TILE_SIZE, TILE_SIZE, image->format->BitsPerPixel, image->format->Rmask, image->format->Gmask, image->format->Bmask, 0);

	newSurface = SDL_DisplayFormat(temp);

	colour = SDL_MapRGB(image->format, TRANS_R, TRANS_G, TRANS_B);

	for (y=0;y<image->h;y+=TILE_SIZE)
	{
		for (x=0;x<image->w;x+=TILE_SIZE)
		{
			SDL_FillRect(newSurface, NULL, colour);

			src.x = x;
			src.y = y;
			src.w = image->w - x >= TILE_SIZE ? TILE_SIZE : image->w - x;
			src.h = image->h - y >= TILE_SIZE ? TILE_SIZE : image->h - y;

			dest.x = 0;
			dest.y = 0;
			dest.w = src.w;
			dest.h = src.h;

			SDL_BlitSurface(image, &src, newSurface, &dest);

			sprintf(name, "%d.png", i);

			OK = 0;

			for (yy=0;yy<newSurface->h;yy++)
			{
				for (xx=0;xx<newSurface->w;xx++)
				{
					pixels = (int *)newSurface->pixels;

					pixel = pixels[(yy * newSurface->w) + xx];

					SDL_GetRGB(pixel, newSurface->format, &r, &g, &b);

					if (r != TRANS_R && g != TRANS_G && b != TRANS_B)
					{
						OK = 1;

						break;
					}
				}
			}

			if (OK == 1 && isDuplicate(newSurface, startIndex, i) == FALSE)
			{
				printf("Saving %s\n", name);

				savePNG(newSurface, name);

				i++;
			}

		}
	}

	exit(0);
}
bool QComposeInputContext::checkComposeTable()
{
    QVector<QComposeTableElement>::const_iterator it =
            std::lower_bound(m_composeTable.constBegin(), m_composeTable.constEnd(), m_composeBuffer, Compare());

    // prevent dereferencing an 'end' iterator, which would result in a crash
    if (it == m_composeTable.constEnd())
        it -= 1;

    QComposeTableElement elem = *it;
    // would be nicer if qLowerBound had API that tells if the item was actually found
    if (m_composeBuffer[0] != elem.keys[0]) {
#ifdef DEBUG_COMPOSING
        qDebug( "### no match ###" );
#endif
        reset();
        return false;
    }
    // check if compose buffer is matched
    for (int i=0; i < QT_KEYSEQUENCE_MAX_LEN; i++) {

        // check if partial match
        if (m_composeBuffer[i] == 0 && elem.keys[i]) {
#ifdef DEBUG_COMPOSING
            qDebug("### partial match ###");
#endif
            return true;
        }

        if (m_composeBuffer[i] != elem.keys[i]) {
#ifdef DEBUG_COMPOSING
            qDebug("### different entry ###");
#endif
            reset();
            return i != 0;
        }
    }
#ifdef DEBUG_COMPOSING
    qDebug("### match exactly ###");
#endif

    // check if the key sequence is overwriten - see the comment in
    // TableGenerator::orderComposeTable()
    int next = 1;
    do {
        // if we are at the end of the table, then we have nothing to do here
        if (it + next != m_composeTable.end()) {
            QComposeTableElement nextElem = *(it + next);
            if (isDuplicate(elem, nextElem)) {
                elem = nextElem;
                next++;
                continue;
            } else {
                break;
            }
        }
        break;
    } while (true);

    commitText(elem.value);
    reset();

    return true;
}
Exemplo n.º 15
0
    WirelessParser::ParsePacketResult WirelessParser::parseAsPacket_ASPP_v2(DataBuffer& data, WirelessPacket& packet, WirelessTypes::Frequency freq)
    {
        //Assume we are at the start of the packet, read the packet header
        //byte 1         - Start Of Packet
        //byte 2         - Delivery Stop Flag
        //byte 3         - App Data Type
        //byte 4 - 7     - Node Address (uint32)
        //byte 8 - 9     - Payload Length
        //byte 10 to N-4 - Payload
        //byte N-3       - Node RSSI
        //byte N-2       - Base RSSI
        //byte N-1       - Fletcher Checksum (MSB)
        //byte N         - Fletcher Checksum (LSB)

        //create a save point for the DataBuffer
        ReadBufferSavePoint savePoint(&data);

        std::size_t totalBytesAvailable = data.bytesRemaining();

        //we need at least 13 bytes for any ASPP v2 packet (if empty payload)
        if(totalBytesAvailable < 13)
        {
            //Not Enough Data to tell if valid packet
            return parsePacketResult_notEnoughData;
        }

        //read byte 1
        uint8 startOfPacket = data.read_uint8();                        //Start Of Packet

        //verify that the first byte is the Start Of Packet
        if(startOfPacket != WirelessPacket::ASPP_V2_START_OF_PACKET_BYTE)
        {
            //Invalid Packet
            return parsePacketResult_invalidPacket;
        }

        //read byte 2
        uint8 deliveryStopFlag = data.read_uint8();                     //Delivery Stop Flag

        //read byte 3
        uint8 appDataType = data.read_uint8();                          //App Data Type

        //read bytes 4 - 7 
        uint32 nodeAddress = data.read_uint32();                        //Node Address

        //read bytes 8 and 9
        uint16 payloadLength = data.read_uint16();                      //Payload Length

        //determine the full packet length 
        size_t packetLength = payloadLength + WirelessPacket::ASPP_V2_NUM_BYTES_BEFORE_PAYLOAD + WirelessPacket::ASPP_V2_NUM_BYTES_AFTER_PAYLOAD;

        //the DataBuffer must be large enough to hold the rest of the packet
        if(totalBytesAvailable < packetLength)
        {
            //Not Enough Data to tell if valid packet
            return parsePacketResult_notEnoughData;
        }

        //create the Bytes vector to hold the payload bytes
        Bytes payload;
        payload.reserve(payloadLength);

        //loop through the payload
        for(uint16 payloadItr = 0; payloadItr < payloadLength; payloadItr++)
        {
            //store the payload bytes
            payload.push_back(data.read_uint8());                        //Payload Bytes
        }

        //read the node RSSI
        uint8 nodeRSSI = data.read_uint8();                             //Node RSSI

        //read the base station rssi
        uint8 baseRSSI = data.read_uint8();                             //Base RSSI

        //get the checksum sent in the packet
        uint16 checksum = data.read_uint16();                           //Checksum

        //build the checksum to calculate from all the bytes
        ChecksumBuilder calcChecksum;
        calcChecksum.append_uint8(startOfPacket);
        calcChecksum.append_uint8(deliveryStopFlag);
        calcChecksum.append_uint8(appDataType);
        calcChecksum.append_uint32(nodeAddress);
        calcChecksum.append_uint16(payloadLength);
        calcChecksum.appendBytes(payload);
        calcChecksum.append_uint8(nodeRSSI);
        calcChecksum.append_uint8(baseRSSI);

        //verify that the returned checksum is the same as the one we calculated
        if(checksum != calcChecksum.fletcherChecksum())
        {
            //Bad Checksum
            return parsePacketResult_badChecksum;
        }

        DeliveryStopFlags flags = DeliveryStopFlags::fromByte(deliveryStopFlag);

        //add all the info about the packet to the WirelessPacket reference passed in
        packet.deliveryStopFlags(flags);
        packet.type(static_cast<WirelessPacket::PacketType>(appDataType));
        packet.nodeAddress(nodeAddress);
        packet.payload(payload);
        packet.nodeRSSI(static_cast<int16>(nodeRSSI) - 205);
        packet.baseRSSI(static_cast<int16>(baseRSSI) - 205);
        packet.frequency(freq);

        //Correct the packet type if it is incorrect
        WirelessPacketUtils::correctPacketType(packet);

        //make sure the packet is valid based on its specific type
        if(!WirelessPacketUtils::packetIntegrityCheck(packet))
        {
            //not a valid packet, failed integrity check
            return parsePacketResult_invalidPacket;
        }

        //check if the packet is a duplicate
        if(isDuplicate(packet))
        {
            //even though it is a duplicate, we still have a complete packet so commit the bytes to skip over them
            savePoint.commit();

            //duplicate packet
            return parsePacketResult_duplicate;
        }

        //we have a complete packet, commit the bytes that we just read (move the read pointer)
        savePoint.commit();

        return parsePacketResult_completePacket;
    }
/** Check if this packet is a duplicate
 *
 * Registers the sequence number as received if it is the first copy of the packet.
 * All subsequent received copies (duplicates) are dropped and the packet count is
 * increased, if the first copy is still in the packet trap.
 *
 * Looping packets sent by this host are also dropped.
 * The hop count value in the corresponding extension is incremented.
 */
int checkSeq(dessert_msg_t* msg, size_t len, dessert_msg_proc_t *proc, dessert_meshif_t *iface, dessert_frameid_t id) {
    if(/*proc->lflags & DESSERT_RX_FLAG_L2_SRC
    ||*/ proc->lflags & DESSERT_RX_FLAG_L25_SRC) {
        // TODO gossip_10
        dessert_debug("dropped looping packet from myself");
        return DESSERT_MSG_DROP;
    }

    seqlog_t* s = NULL;
    u_char* shost = dessert_msg_getl25ether(msg)->ether_shost;

    /*###*/
    pthread_rwlock_rdlock(&seqlog_lock);
    HASH_FIND(hh, seqlog, shost, ETHER_ADDR_LEN, s);
    pthread_rwlock_unlock(&seqlog_lock);
    /*###*/

    bool seq2_duplicate = false;
    if(s) {
        /*###*/
        pthread_rwlock_wrlock(&seqlog_lock);
        uint8_t dup = isDuplicate(s, msg->u16);
        if(!dup) {
            insertSeq(s, msg->u16);
#ifndef ANDROID
            seq2_duplicate = gossip13_rx_packet(s, msg, false);
#endif
            pthread_rwlock_unlock(&seqlog_lock);
            /*###*/
        }
        else {
            pthread_rwlock_unlock(&seqlog_lock);
            /*###*/
            if(!(msg->u8 & HELLO)) { // HELLOs are never trapped
                trappedpacket_t* t;
                pkey_t lookup_key;
                memcpy(lookup_key.addr, shost, ETHER_ADDR_LEN);
                lookup_key.seq = msg->u16;

                /*###*/
                pthread_rwlock_wrlock(&packettrap_lock);
                HASH_FIND(hh, trappedpackets, &lookup_key, sizeof(pkey_t), t);
                if(t) {
                    // TODO gossip_10
                    t->counter++;
                }
                pthread_rwlock_unlock(&packettrap_lock);
                /*###*/
            }
            return DESSERT_MSG_DROP;
        }
    }
    else {
        s = malloc(sizeof(seqlog_t));
        if(!s) {
            dessert_crit("could not allocate memory");
            return DESSERT_MSG_KEEP;
        }
        uint16_t i = 0;
        for(i=0; i<LOG_SIZE; i++) {
            s->seqs[i] = msg->u16;
        }
        s->next_seq = 1;
#ifndef ANDROID
        // what the other node tells me
        gossip13_new_history(&(s->rx_history), false); // does not require observation initialization
        gossip13_new_history(&(s->tx_history), false); // does not require observation initialization
        gossip13_new_history(&(s->total_tx_history), false); // does not require observation initialization
        gossip13_new_history_mean(&(s->hops_history), false); // does not require observation initialization
        gossip13_new_history(&(s->nodes_history), false); // does not require observation initialization
        gossip13_new_history_mean(&(s->mean_dist_history), false); // does not require observation initialization
        gossip13_new_history_mean(&(s->eccentricity_history), false); // does not require observation initialization

        // what I know about the other node
        gossip13_new_history(&(s->observed_history), true);
        gossip13_new_observation(&(s->observed_history->observations));
        gossip13_new_history_mean(&(s->my_hops_history), true);
        gossip13_new_observation_mean(&(s->my_hops_history->observations));
#endif

        s->tau = 0;
        memcpy(s->addr, shost, ETHER_ADDR_LEN);
        dessert_debug("registering seq=%d for src=" MAC " (previously unknown host)", msg->u16, EXPLODE_ARRAY6(shost));
#ifndef ANDROID
        seq2_duplicate = gossip13_rx_packet(s, msg, true);
#endif

        /*###*/
        pthread_rwlock_wrlock(&seqlog_lock);
        HASH_ADD(hh, seqlog, addr, ETHER_ADDR_LEN, s);
        pthread_rwlock_unlock(&seqlog_lock);
        /*###*/
    }
#ifndef ANDROID
    if(seq2_duplicate && gossip13_drop_seq2_duplicates
        && (proc->lflags & DESSERT_RX_FLAG_L25_DST || proc->lflags & DESSERT_RX_FLAG_L25_BROADCAST)) {
        return DESSERT_MSG_DROP;
    }
#endif

    dessert_ext_t* ext = NULL;
    if(dessert_msg_getext(msg, &ext, EXT_HOPS, 0)) {
        gossip_ext_hops_t* h = (gossip_ext_hops_t*) ext->data;
        h->hops++;
    }
    return DESSERT_MSG_KEEP;
}
Exemplo n.º 17
0
//add a task into specified index in _tasks
//used for undo only as _entryOrder need to be maintained
void RunTimeStorage::insert(Task task, size_t index) {
	assert(!isDuplicate(task));
	_tasks.insert(_tasks.begin()+index, task);
	return;
}
Exemplo n.º 18
0
void KeyDefMenuUserInterface::render() const
{
   // Draw the game screen, then dim it out so you can still see it under our overlay
   if(getGame()->getConnectionToServer())
      getUIManager()->renderAndDimGameUserInterface();

   mGL->glColor(Colors::white);
   RenderUtils::drawCenteredString(vertMargin, 30, mMenuTitle);
   RenderUtils::drawCenteredString(vertMargin + 35, 18, mMenuSubTitle);

   mGL->glColor(Colors::menuHelpColor);
   RenderUtils::drawCenteredString(vertMargin + 63, 14, "You can define different keys for keyboard or joystick mode.  Switch in Options menu.");

   mGL->glColor(Colors::white);
   RenderUtils::drawCenteredString(DisplayManager::getScreenInfo()->getGameCanvasHeight() - vertMargin - 20, 18, mMenuFooter);

   TNLAssert(selectedIndex < menuItems.size(), "Index out of bounds!");
   //if(selectedIndex >= menuItems.size())
   //   selectedIndex = 0;

   S32 size = menuItems.size();

   for(S32 i = 0; i < size; i++)
   {
      S32 y = yStart + (i - ((i < firstItemInCol2) ? 0 : firstItemInCol2)) * height;

		S32 Column_Width = DisplayManager::getScreenInfo()->getGameCanvasWidth() / 2 - horizMargin;
		S32 xPos = (menuItems[i].column - 1) * Column_Width + horizMargin * 2;

      if(selectedIndex == i)       // Highlight selected item
         RenderUtils::drawFilledRect(xPos - horizMargin, y,
                        xPos + Column_Width - horizMargin, y + height + 1, 
                        Colors::blue40, Colors::blue);

      // Draw item text
      mGL->glColor(Colors::cyan);
      RenderUtils::drawString(xPos, y + offset, 15, menuItems[i].text);

		xPos += Column_Width * 14 / 20;

      if(mChangingItem == i)
      {
         mGL->glColor(Colors::red);
         RenderUtils::drawString(xPos, y + offset + 1, 13, "Press Key or Button");
      }
      else
      {
         bool dupe = isDuplicate(i, menuItems); 
         const Color *color = dupe ? &Colors::red : NULL;

         JoystickRender::renderControllerButton(F32(xPos), F32(y + offset), 
                               Joystick::SelectedPresetIndex, getInputCode(mGameSettings, menuItems[i].primaryControl), color);
      }
   }

   S32 yPos = yStart + maxMenuItemsInAnyCol * height + 10;

   // Draw the help string
   mGL->glColor(Colors::green);
   RenderUtils::drawCenteredString(yPos, 15, menuItems[selectedIndex].helpString.c_str());

   yPos += 20;

   // Draw some suggestions
   mGL->glColor(Colors::yellow);
   if(getGame()->getInputMode() == InputModeJoystick)
      RenderUtils::drawCenteredString(yPos, 15, "HINT: You will be using the left joystick to steer, the right to fire");
   else
      RenderUtils::drawCenteredString(yPos, 15, "HINT: You will be using the mouse to aim, so make good use of your mouse buttons");

   if(errorMsgTimer.getCurrent())
   {
      yPos += 20;
      F32 alpha = 1.0;
      if(errorMsgTimer.getCurrent() < 1000)
         alpha = (F32) errorMsgTimer.getCurrent() / 1000;

      mGL->glColor(Colors::red, alpha);
      RenderUtils::drawCenteredString(yPos, 15, errorMsg.c_str());
   }
}