char *XP_Cat(char *a0, ...) { va_list ap; char *a, *result, *cp; int len; /* Count up string length's */ va_start(ap, a0); len = 1; a = a0; while (a != (char*) NULL) { len += XP_STRLEN(a); a = va_arg(ap, char*); } va_end(ap); /* Allocate memory and copy strings */ va_start(ap, a0); result = cp = (char*) XP_ALLOC(len); if (!cp) return 0; a = a0; while (a != (char*) NULL) { len = XP_STRLEN(a); XP_MEMCPY(cp, a, len); cp += len; a = va_arg(ap, char*); } *cp = 0; va_end(ap); return result; }
static void invalBlanksWithNeighbors( BoardCtxt* board, BlankQueue* bqp ) { XP_U16 ii; XP_U16 lastCol, lastRow; BlankQueue invalBlanks; XP_U16 nInvalBlanks = 0; lastCol = model_numCols(board->model) - 1; lastRow = model_numRows(board->model) - 1; for ( ii = 0; ii < bqp->nBlanks; ++ii ) { XP_U16 modelCol = bqp->col[ii]; XP_U16 modelRow = bqp->row[ii]; XP_U16 col, row; flipIf( board, modelCol, modelRow, &col, &row ); if ( INVAL_BIT_SET( board, col, row ) || (col > 0 && INVAL_BIT_SET( board, col-1, row )) || (col < lastCol && INVAL_BIT_SET( board, col+1, row )) || (row > 0 && INVAL_BIT_SET( board, col, row-1 )) || (row < lastRow && INVAL_BIT_SET( board, col, row+1 )) ) { invalCell( board, col, row ); invalBlanks.col[nInvalBlanks] = (XP_U8)col; invalBlanks.row[nInvalBlanks] = (XP_U8)row; ++nInvalBlanks; } } invalBlanks.nBlanks = nInvalBlanks; XP_MEMCPY( bqp, &invalBlanks, sizeof(*bqp) ); } /* invalBlanksWithNeighbors */
static XP_Bool and_util_askPassword( XW_UtilCtxt* uc, const XP_UCHAR* name, XP_UCHAR* buf, XP_U16* len ) { XP_Bool result = false; UTIL_CBK_HEADER("askPassword", "(Ljava/lang/String;)Ljava/lang/String;" ); jstring jname = (*env)->NewStringUTF( env, name ); jstring jstr = (*env)->CallObjectMethod( env, util->jutil, mid, jname ); deleteLocalRef( env, jname ); if ( NULL != jstr ) { /* null means user cancelled */ jsize jsiz = (*env)->GetStringUTFLength( env, jstr ); if ( jsiz < *len ) { const char* chars = (*env)->GetStringUTFChars( env, jstr, NULL ); XP_MEMCPY( buf, chars, jsiz ); (*env)->ReleaseStringUTFChars( env, jstr, chars ); buf[jsiz] = '\0'; *len = jsiz; result = XP_TRUE; } deleteLocalRef( env, jstr ); } UTIL_CBK_TAIL(); return result; }
static void copyIter( DictIter* dest, const DictIter* src ) { XP_U16 nEdges = src->nEdges; dest->nEdges = nEdges; XP_MEMCPY( dest->edges, src->edges, nEdges * sizeof(dest->edges[0]) ); }
/* binary block Allocate and Concatenate * * destination_length is the length of the existing block * source_length is the length of the block being added to the * destination block */ PUBLIC char * NET_BACat (char **destination, size_t destination_length, const char *source, size_t source_length) { if (source) { if (*destination) { *destination = (char *) XP_REALLOC (*destination, destination_length + source_length); if (*destination == NULL) return(NULL); XP_MEMMOVE (*destination + destination_length, source, source_length); } else { *destination = (char *) XP_ALLOC (source_length); if (*destination == NULL) return(NULL); XP_MEMCPY(*destination, source, source_length); } } return *destination; }
static const XP_UCHAR* and_util_getUserString( XW_UtilCtxt* uc, XP_U16 stringCode ) { XP_UCHAR* result = ""; UTIL_CBK_HEADER("getUserString", "(I)Ljava/lang/String;" ); int index = stringCode - 1; /* see LocalizedStrIncludes.h */ XP_ASSERT( index < VSIZE( util->userStrings ) ); if ( ! util->userStrings[index] ) { jstring jresult = (*env)->CallObjectMethod( env, util->jutil, mid, stringCode ); jsize len = (*env)->GetStringUTFLength( env, jresult ); XP_UCHAR* buf = XP_MALLOC( util->util.mpool, len + 1 ); const char* jchars = (*env)->GetStringUTFChars( env, jresult, NULL ); XP_MEMCPY( buf, jchars, len ); buf[len] = '\0'; (*env)->ReleaseStringUTFChars( env, jresult, jchars ); deleteLocalRef( env, jresult ); util->userStrings[index] = buf; } result = util->userStrings[index]; UTIL_CBK_TAIL(); return result; }
/* Remove a select if it exists. */ PRIVATE void net_remove_select(SelectType stType, PRFileDesc *prFD) { unsigned int count; /* Go through the list */ for(count=0; count < fd_set_size; count++) { if(poll_desc_array[count].fd == prFD) { if((stType == ConnectSelect && poll_desc_array[count].in_flags == CONNECT_FLAGS) || (stType == ReadSelect && poll_desc_array[count].in_flags == READ_FLAGS)) { /* found it collapse the list */ fd_set_size--; if(count < fd_set_size) XP_MEMCPY(&poll_desc_array[count], &poll_desc_array[count+1], (fd_set_size - count) * sizeof(PRPollDesc)); return; } } } /* didn't find it. opps */ }
static const XP_UCHAR* and_util_getDevID( XW_UtilCtxt* uc, DevIDType* typ ) { const XP_UCHAR* result = NULL; *typ = ID_TYPE_NONE; UTIL_CBK_HEADER( "getDevID", "([B)Ljava/lang/String;" ); jbyteArray jbarr = makeByteArray( env, 1, NULL ); jstring jresult = (*env)->CallObjectMethod( env, util->jutil, mid, jbarr ); if ( NULL != jresult ) { const char* jchars = (*env)->GetStringUTFChars( env, jresult, NULL ); jsize len = (*env)->GetStringUTFLength( env, jresult ); if ( NULL != util->devIDStorage && 0 == XP_MEMCMP( util->devIDStorage, jchars, len ) ) { XP_LOGF( "%s: already have matching devID", __func__ ); } else { XP_LOGF( "%s: allocating storage for devID", __func__ ); XP_FREEP( util->util.mpool, &util->devIDStorage ); util->devIDStorage = XP_MALLOC( util->util.mpool, len + 1 ); XP_MEMCPY( util->devIDStorage, jchars, len ); util->devIDStorage[len] = '\0'; } (*env)->ReleaseStringUTFChars( env, jresult, jchars ); result = (const XP_UCHAR*)util->devIDStorage; jbyte* elems = (*env)->GetByteArrayElements( env, jbarr, NULL ); *typ = (DevIDType)elems[0]; (*env)->ReleaseByteArrayElements( env, jbarr, elems, 0 ); } deleteLocalRef( env, jbarr ); UTIL_CBK_TAIL(); return result; }
char *XP_AppendStr(char *in, const char *append) { int alen, inlen; alen = XP_STRLEN(append); if (in) { inlen = XP_STRLEN(in); in = (char*) XP_REALLOC(in,inlen+alen+1); if (in) { XP_MEMCPY(in+inlen, append, alen+1); } } else { in = (char*) XP_ALLOC(alen+1); if (in) { XP_MEMCPY(in, append, alen+1); } } return in; }
/* * Appends the name/value list in count2, names2, and values2 on * to the name/value list in count1, names1, and values1. */ void lo_AppendParamList(uint32* count1, char*** names1, char*** values1, uint32 count2, char** names2, char** values2) { char** names = NULL; char** values = NULL; if (*names1 != NULL) { if (names2 != NULL) { names = (char**) XP_REALLOC(*names1, ((*count1 + count2) * sizeof(char*))); if (names != NULL) XP_MEMCPY(&(names[*count1]), names2, count2 * sizeof(char*)); } else names = *names1; } else names = names2; if (*values1 != NULL) { if (values2 != NULL) { values = (char**) XP_REALLOC(*values1, ((*count1 + count2) * sizeof(char*))); if (values != NULL) XP_MEMCPY(&(values[*count1]), values2, count2 * sizeof(char*)); } else values = *values1; } else values = values2; if (names != NULL && values != NULL) { *count1 = *count1 + count2; *names1 = names; *values1 = values; } }
PRIVATE int NET_ParseHTMLHelpPut(HTMLHelpParseObj *obj, char *str, int32 len) { int32 string_len; char *new_line; int32 status; if(!obj) return(MK_OUT_OF_MEMORY); /* buffer until we have a line */ BlockAllocCat(obj->line_buffer, obj->line_buffer_size, str, len); obj->line_buffer_size += len; /* see if we have a line */ while((new_line = strchr_in_buf(obj->line_buffer, obj->line_buffer_size, LF)) != NULL || ((new_line = strchr_in_buf(obj->line_buffer, obj->line_buffer_size, CR)) != NULL) ) { /* terminate the line */ *new_line = '\0'; status = net_ParseHTMLHelpLine(obj, obj->line_buffer); /* remove the parsed line from obj->line_buffer */ string_len = (new_line - obj->line_buffer) + 1; XP_MEMCPY(obj->line_buffer, new_line+1, obj->line_buffer_size-string_len); obj->line_buffer_size -= string_len; if(status == HTML_HELP_ID_FOUND) return(HTML_HELP_ID_FOUND); } return(0); }
void CStreamOutNet::Write( char *pBuffer, int32 iCount ){ // Buffer the output. // pBuffer may be a const string, even a ROM string. // (e.g. string constants on a Mac with VM.) // But networking does in-place transformations on the // data to convert it into other character sets. const int32 kBufferSize = 128; char buffer[kBufferSize]; if (m_pStream == NULL) { // if we're trying to write with a null stream, we have definately // tripped over an error m_status = EOS_FileError; return; } while ( iCount > 0 ) { int32 iChunkSize = iCount; if ( iChunkSize > kBufferSize ) { iChunkSize = kBufferSize; } XP_MEMCPY(buffer, pBuffer, iChunkSize); int status = (*m_pStream->put_block)(m_pStream, buffer, iChunkSize ); if(status < 0){ m_status = EOS_FileError; (*m_pStream->abort)(m_pStream, status); XP_FREE(m_pStream); m_pStream = NULL; break; } // status?? iCount -= iChunkSize; } }
/* Allocate a new copy of a block of binary data, and returns it */ PUBLIC char * NET_BACopy (char **destination, const char *source, size_t length) { if(*destination) { XP_FREE(*destination); *destination = 0; } if (! source) { *destination = NULL; } else { *destination = (char *) XP_ALLOC (length); if (*destination == NULL) return(NULL); XP_MEMCPY(*destination, source, length); } return *destination; }
void CConvertCSIDStreamOut::Write( char* pBuffer, int32 iCount ){ if ( ! m_pStream ) { return; } if ( m_bNullConversion ) { m_pStream->Write(pBuffer, iCount); } else { // INTL_CallCharaCodeConverter has a pecuilar calling convention. // if the converion is a no-op, the argument is returned. // if pToData hasn't changed it won't be null-terminated // else it **MUST** be NULL-terminated so we can get the new length // The character code converter will trash the input string under // some circumstances, as for example if a Mac is transcoding to // ISO-Latin-1. Therefore we must copy the input stream. char* pCopy = (char*) XP_ALLOC(iCount); if ( pCopy == NULL) { XP_ASSERT(FALSE); return; } XP_MEMCPY(pCopy, pBuffer, iCount); char* pToData = (char*) INTL_CallCharCodeConverter(m_Converter, (const unsigned char*) pCopy, iCount); if ( pToData ) { if ( pToData != pCopy ) iCount = XP_STRLEN(pToData); m_pStream->Write(pToData, iCount); if ( pToData != pCopy ) { XP_FREE(pToData); } } else { // Some sort of error. XP_ASSERT(FALSE); m_pStream->Write(pCopy, iCount); } XP_FREE(pCopy); } }
static void indexOne( XP_U16 depth, Tile* tiles, IndexData* data, DictIter* prevIter, DictPosition* prevIndex ) { DictIter curIter; dict_initIterFrom( &curIter, prevIter ); if ( findWordStartsWith( &curIter, tiles, depth ) ) { while ( !wordsEqual( &curIter, prevIter ) ) { ++*prevIndex; if ( !nextWord( prevIter ) ) { XP_ASSERT( 0 ); } } XP_ASSERT( data->count == 0 || data->indices[data->count-1] < *prevIndex ); data->indices[data->count] = *prevIndex; if ( NULL != data->prefixes ) { XP_MEMCPY( data->prefixes + (data->count * depth), tiles, depth ); } ++data->count; } }
/* * Write out a separator entry. See comment at the top of * hot_measure_Separator for the format used. Assume we start writing at * the start of the buffer passed in. Return a pointer to where the * buffer ends when we get done. */ PRIVATE char * hot_write_Separator(char * buffer, HotlistStruct * item, int bLongFormat, int nIndent) { int iLen; #if 0 int32 lVal; #endif int32 sVal; if(!item || !buffer) return(buffer); if(bLongFormat) { /* copy the type */ sVal = (int16) item->type; iLen = 2; XP_MEMCPY(buffer, &sVal, iLen); buffer += iLen; } else { XP_MEMSET(buffer, ' ', nIndent); buffer += nIndent; XP_MEMSET(buffer, '-', SEPATATOR_COUNT); buffer += SEPATATOR_COUNT; *buffer++ = '\n'; } return(buffer); }
void drawScoreBoard( BoardCtxt* board ) { if ( board->scoreBoardInvalid ) { short ii; XP_U16 nPlayers = board->gi->nPlayers; XP_ASSERT( nPlayers <= MAX_NUM_PLAYERS ); if ( nPlayers > 0 ) { ModelCtxt* model = board->model; XP_S16 curTurn = server_getCurrentTurn( board->server ); XP_U16 selPlayer = board->selPlayer; XP_S16 nTilesInPool = server_countTilesInPool( board->server ); XP_Rect scoreRect = board->scoreBdBounds; XP_S16* adjustDim; XP_S16* adjustPt; XP_U16 remWidth, remHeight, remDim; DrawScoreData* dp; DrawScoreData datum[MAX_NUM_PLAYERS]; ScoresArray scores; XP_Bool isVertical = !board->scoreSplitHor; XP_Bool remFocussed = XP_FALSE; XP_Bool focusAll = XP_FALSE; #ifdef KEYBOARD_NAV XP_S16 cursorIndex = -1; if ( (board->focussed == OBJ_SCORE) && !board->hideFocus ) { focusAll = !board->focusHasDived; if ( !focusAll ) { cursorIndex = board->scoreCursorLoc; remFocussed = CURSOR_LOC_REM == cursorIndex; --cursorIndex; } } #endif /* Get the scores from the model or by calculating them based on the end-of-game state. */ if ( board->gameOver ) { model_figureFinalScores( model, &scores, NULL ); } else { for ( ii = 0; ii < nPlayers; ++ii ) { scores.arr[ii] = model_getPlayerScore( model, ii ); } } if ( draw_scoreBegin( board->draw, &board->scoreBdBounds, nPlayers, scores.arr, nTilesInPool, dfsFor( board, OBJ_SCORE ) ) ) { XP_U16 totalDim = 0; /* not counting rem */ XP_U16 gotPct; /* Let platform decide whether the rem: string should be given any space once there are no tiles left. On Palm that space is clickable to drop a menu, so will probably leave it. */ if ( !draw_measureRemText( board->draw, &board->scoreBdBounds, nTilesInPool, &remWidth, &remHeight ) ) { remWidth = remHeight = 0; } XP_ASSERT( remWidth <= board->scoreBdBounds.width ); XP_ASSERT( remHeight <= board->scoreBdBounds.height ); remDim = isVertical? remHeight : remWidth; if ( isVertical ) { adjustPt = &scoreRect.top; adjustDim = &scoreRect.height; } else { adjustPt = &scoreRect.left; adjustDim = &scoreRect.width; } *adjustDim -= remDim; /* Give as much room as possible to the entry for the player whose turn it is so name can be drawn. Do that by formatting that player's score last, and passing each time the amount of space left. Platform code can then fill that space. */ /* figure spacing for each scoreboard entry */ XP_MEMSET( &datum, 0, sizeof(datum) ); totalDim = 0; for ( dp = datum, ii = 0; ii < nPlayers; ++ii, ++dp ) { LocalPlayer* lp = &board->gi->players[ii]; /* This is a hack! */ dp->dsi.lsc = board_ScoreCallback; dp->dsi.lscClosure = model; #ifdef KEYBOARD_NAV if ( (ii == cursorIndex) || focusAll ) { dp->dsi.flags |= CELL_ISCURSOR; } #endif dp->dsi.playerNum = ii; dp->dsi.totalScore = scores.arr[ii]; dp->dsi.isTurn = (ii == curTurn); dp->dsi.name = emptyStringIfNull(lp->name); dp->dsi.selected = board->trayVisState != TRAY_HIDDEN && ii==selPlayer; dp->dsi.isRobot = LP_IS_ROBOT(lp); dp->dsi.isRemote = !lp->isLocal; dp->dsi.nTilesLeft = (nTilesInPool > 0)? -1: model_getNumTilesTotal( model, ii ); draw_measureScoreText( board->draw, &scoreRect, &dp->dsi, &dp->width, &dp->height ); XP_ASSERT( dp->width <= scoreRect.width ); XP_ASSERT( dp->height <= scoreRect.height ); totalDim += isVertical ? dp->height : dp->width; } gotPct = (*adjustDim * 100) / totalDim; for ( dp = datum, ii = 0; ii < nPlayers; ++ii, ++dp ) { if ( isVertical ) { dp->height = (dp->height * gotPct) / 100; } else { dp->width = (dp->width * gotPct) / 100; } } scoreRect = board->scoreBdBounds; /* reset */ /* at this point, the scoreRect should be anchored at the scoreboard rect's upper left. */ if ( remDim > 0 ) { XP_Rect innerRect; *adjustDim = remDim; centerIn( &innerRect, &scoreRect, remWidth, remHeight ); draw_drawRemText( board->draw, &innerRect, &scoreRect, nTilesInPool, focusAll || remFocussed ); *adjustPt += remDim; #ifdef KEYBOARD_NAV board->remRect = scoreRect; /* Hack: don't let the cursor disappear if Rem: goes away */ } else if ( board->scoreCursorLoc == CURSOR_LOC_REM ) { board->scoreCursorLoc = selPlayer + 1; #endif } board->remDim = remDim; for ( dp = datum, ii = 0; ii < nPlayers; ++dp, ++ii ) { XP_Rect innerRect; XP_U16 dim = isVertical? dp->height:dp->width; *adjustDim = board->pti[ii].scoreDims = dim; centerIn( &innerRect, &scoreRect, dp->width, dp->height ); draw_score_drawPlayer( board->draw, &innerRect, &scoreRect, gotPct, &dp->dsi ); #ifdef KEYBOARD_NAV XP_MEMCPY( &board->pti[ii].scoreRects, &scoreRect, sizeof(scoreRect) ); #endif *adjustPt += *adjustDim; } draw_objFinished( board->draw, OBJ_SCORE, &board->scoreBdBounds, dfsFor( board, OBJ_SCORE ) ); board->scoreBoardInvalid = XP_FALSE; } } } drawTimer( board ); } /* drawScoreBoard */
/* * Write out a hotlist header entry. See comment at the top of * hot_measure_Header for the format used. Assume we start writing at * the start of the buffer passed in. Return a pointer to where the * buffer ends when we get done. */ PRIVATE char * hot_write_Header(char * buffer, HotlistStruct * item, int bLongFormat, int nIndent) { XP_List * list; int iLen; int32 lVal; int32 sVal; if(!item || !buffer) return(buffer); if(bLongFormat) { /* copy the type */ sVal = (int16) item->type; iLen = 2; XP_MEMCPY(buffer, &sVal, iLen); buffer += iLen; /* copy the name */ if(item->name) { iLen = XP_STRLEN(item->name); XP_MEMCPY(buffer, item->name, iLen); buffer += iLen; } /* put the \n terminator on */ *buffer++ = '\n'; /* addition date */ lVal = (int32) item->addition_date; iLen = 4; XP_MEMCPY(buffer, &lVal, iLen); buffer += iLen; /* number of children */ lVal = XP_ListCount(item->children); iLen = 4; XP_MEMCPY(buffer, &lVal, iLen); buffer += iLen; /* copy the description */ if(item->description) { iLen = XP_STRLEN(item->description); XP_MEMCPY(buffer, item->description, iLen); buffer += iLen; } /* put the \n terminator on */ *buffer++ = '\0'; } else { XP_MEMSET(buffer, ' ', nIndent); buffer += nIndent; if(item->name) { XP_STRCPY(buffer, item->name); buffer += XP_STRLEN(item->name); } *buffer++ = '\n'; } /* if no children just get out now */ if(!item->children) return(buffer); /* write out the children */ for(list = item->children->next; list; list = list->next) { HotlistStruct * child = (HotlistStruct *) list->object; if(!child) continue; switch(child->type) { case HOT_URLType: buffer = hot_write_URL(buffer, child, bLongFormat, nIndent + TEXT_INDENT); break; case HOT_HeaderType: buffer = hot_write_Header(buffer, child, bLongFormat, nIndent + TEXT_INDENT); break; case HOT_SeparatorType: buffer = hot_write_Separator(buffer, child, bLongFormat, nIndent + TEXT_INDENT); break; default: break; } } return(buffer); }
/* * Take a URL packed in a block the way hot_write_URL packs it. * Return the new item if we created one */ PRIVATE HotlistStruct * hot_read_URL(char * buffer, HotlistStruct * pListParent, HotlistStruct * item, int bLongFormat, int32 * lBytesEaten) { HotlistStruct * new_item = NULL; if(!buffer) return(NULL); if(bLongFormat) { int32 addition, visit; /* get the name */ char * name = buffer; char * address = strchr(name, '\n'); char * description = NULL; char * ptr; if(!address) return(NULL); *address++ = '\0'; /* get the address */ ptr = strchr(address, '\n'); if(!ptr) return(NULL); *ptr++ = '\0'; /* addition date */ XP_MEMCPY(&addition, ptr, 4); ptr += 4; /* visiting date */ XP_MEMCPY(&visit, ptr, 4); ptr += 4; /* get the description (it should be NULL terminated) */ description = ptr; /* we should really strip leading whitespace */ new_item = HOT_CreateEntry(HOT_URLType, name, address, 0, visit); new_item->addition_date = addition; new_item->description = XP_STRDUP(description); *lBytesEaten = XP_STRLEN(description) + (description - buffer) + 1; } else { char * end = strchr(buffer, '\n'); /* if there was a return NULL terminate the current string */ if(end) *end++ = '\0'; /* we should really strip leading whitespace */ new_item = HOT_CreateEntry(HOT_URLType, buffer, buffer, 0, 0); new_item->addition_date = time ((time_t *) NULL); *lBytesEaten = XP_STRLEN(buffer) + 1; } if(item) HOT_InsertItemAfter(item, new_item); else HOT_InsertItemInHeaderOrAfterItem(pListParent, new_item); return(new_item); }
lo_ObjectStack* lo_PushObject(MWContext* context, lo_DocState* state, PA_Tag* tag) { /* * If possible, reuse an object stack entry created in * a previous pass over this tag (i.e. while blocked, by * lo_BlockObjectTag). If there's no previously-created * object, make a new one. */ lo_TopState* top_state = state->top_state; lo_ObjectStack* new_top = top_state->object_cache; if (new_top != NULL) { /* Find and remove the matching item, if any */ if (new_top->real_tag == tag) top_state->object_cache = new_top->next; else { while (new_top->next != NULL) { if (new_top->next->real_tag == tag) { lo_ObjectStack* temp = new_top->next; new_top->next = new_top->next->next; new_top = temp; break; } new_top = new_top->next; } } } if (new_top == NULL || new_top->real_tag != tag) { new_top = XP_NEW_ZAP(lo_ObjectStack); if (new_top == NULL) { state->top_state->out_of_memory = TRUE; return NULL; } } new_top->next = top_state->object_stack; top_state->object_stack = new_top; new_top->context = context; new_top->state = state; /* * Clone the tag since the tag passed in may be freed * by the parser before we're ready for it. */ if (new_top->real_tag != tag) { new_top->real_tag = tag; if (new_top->clone_tag != NULL) PA_FreeTag(new_top->clone_tag); new_top->clone_tag = XP_NEW(PA_Tag); if (new_top->clone_tag != NULL) { XP_MEMCPY(new_top->clone_tag, tag, sizeof(PA_Tag)); new_top->clone_tag->data = PA_ALLOC((tag->data_len + 1) * sizeof (char)); if (new_top->clone_tag->data != NULL) { char* source; char* dest; PA_LOCK(source, char*, tag->data); PA_LOCK(dest, char*, new_top->clone_tag->data); XP_MEMCPY(dest, source, tag->data_len + 1); PA_UNLOCK(dest); PA_UNLOCK(source); }
/* * Take a header and children packed in a block the way hot_write_Header * packs it. Return the new header item if we created one */ PRIVATE HotlistStruct * hot_read_Header(char * buffer, HotlistStruct * pListParent, HotlistStruct * item, int bLongFormat, int32 * lBytesEaten) { int32 kids = 0; int16 sVal; HotlistStruct * new_item = NULL; if(!buffer) return(NULL); /* can only read long format headers */ if(bLongFormat) { int32 addition; /* get the name */ char * name = buffer; char * ptr = strchr(name, '\n'); char * description = NULL; if(!ptr) return(NULL); /* skip over the \n but change it to a \0 so strcpy() will work */ *ptr++ = '\0'; /* addition date */ XP_MEMCPY(&addition, ptr, 4); ptr += 4; /* number of children to read */ XP_MEMCPY(&kids, ptr, 4); ptr += 4; /* get the description (it should be NULL terminated) */ description = ptr; /* we should really strip leading whitespace */ new_item = HOT_CreateEntry(HOT_HeaderType, name, NULL, 0, 0); new_item->addition_date = addition; new_item->description = XP_STRDUP(description); *lBytesEaten = XP_STRLEN(description) + (description - buffer) + 1; /* handle all of the kids now */ if(kids) { int i; HotlistStruct * kid = NULL; new_item->children = XP_ListNew(); buffer += *lBytesEaten; for(i = 0; i < kids; i++) { int32 lEat; /* determine the type of the next entry */ sVal = 0; XP_MEMCPY(&sVal, buffer, 2); buffer += 2; *lBytesEaten += 2; switch(sVal) { case HOT_URLType: kid = hot_read_URL(buffer, new_item, kid, bLongFormat, &lEat); *lBytesEaten += lEat; buffer += lEat; break; case HOT_HeaderType: kid = hot_read_Header(buffer, new_item, kid, bLongFormat, &lEat); *lBytesEaten += lEat; buffer += lEat; break; case HOT_SeparatorType: kid = hot_read_Separator(buffer, new_item, kid, bLongFormat, &lEat); *lBytesEaten += lEat; buffer += lEat; break; default: /* bogus type. Who knows whats going on. Just quit and get out */ break; } } } else { /* no kids */ new_item->children = NULL; } } if(item) HOT_InsertItemAfter(item, new_item); else HOT_InsertItemInHeaderOrAfterItem(pListParent, new_item); return(new_item); }
/* * Allocate and return a string that contains the text representation of * a list of hotlist entries (including headers and their contents). * The caller is responsible for freeing the string */ PUBLIC char * HOT_ConvertSelectionsToBlock(HotlistStruct ** list, int iCount, int bLongFormat, int32 * lTotalLen) { int i, j; int bSkip; int16 marker; int32 iSpace = 0; HotlistStruct * item; HotlistStruct * pParent; char * pString; char * pOriginal; for(i = 0; i < iCount; i++) { /* don't skip yet */ bSkip = FALSE; /* make sure we have a valid item */ item = list[i]; if(!item) continue; /* * if our parent is in the list don't add ourselves, we will have * been added when our parent got added. Ugh. This is going to be * n^2 over the number of selected items */ for(pParent = item->parent; pParent && !bSkip; pParent = pParent->parent) { for(j = 0; (j < iCount) && (!bSkip) ; j++) if(list[j] == pParent) bSkip = TRUE; } if(bSkip) continue; /* decide how much space we need */ switch(item->type) { case HOT_URLType: iSpace += hot_measure_URL(item, bLongFormat, 0); break; case HOT_HeaderType: iSpace += hot_measure_Header(item, bLongFormat, 0); break; case HOT_SeparatorType: iSpace += hot_measure_Separator(item, bLongFormat, 0); break; default: break; } } /* leave room for end of list marker */ if(bLongFormat) iSpace += 2; /* leave room for the termination character */ iSpace++; #ifdef XP_WIN16 if(iSpace > 32000) return(NULL); #endif /* allocate the string */ pOriginal = pString = (char *) XP_ALLOC(iSpace * sizeof(char)); if(!pString) return(NULL); /* Make a big string */ for(i = 0; i < iCount; i++) { bSkip = FALSE; /* make sure we have a valid item */ item = list[i]; if(!item) continue; /* * if our parent is in the list don't add ourselves, we will have * been added when our parent got added. Ugh. This is going to be * n^2 over the number of selected items */ for(pParent = item->parent; pParent && !bSkip; pParent = pParent->parent) { for(j = 0; (j < iCount) && (!bSkip) ; j++) if(list[j] == pParent) bSkip = TRUE; } if(bSkip) continue; /* write out the item */ switch(item->type) { case HOT_URLType: pString = hot_write_URL(pString, item, bLongFormat, 0); break; case HOT_HeaderType: pString = hot_write_Header(pString, item, bLongFormat, 0); break; case HOT_SeparatorType: pString = hot_write_Separator(pString, item, bLongFormat, 0); break; default: break; } } /* stick the end of list marker on so that when we are decoding this */ /* block we know when we are done */ if(bLongFormat) { marker = 12345; XP_MEMCPY(pString, &marker, 2); pString +=2; } /* end the string and return the total length to our caller */ *pString++ = '\0'; *lTotalLen = (pString - pOriginal); return(pOriginal); }
/* * Take a block of memory formatted by HOT_ConvertSelectionsToBlock and insert * the items it represents into the hotlist following 'item'. If item is * NULL insert at the beginning of the hotlist. */ PUBLIC void HOT_InsertBlockAt(char * pOriginalBlock, HotlistStruct * item, int bLongFormat, int32 lTotalLen) { int16 sVal; /* 16-bit scratch variable */ int32 lBytesEaten = 0; /* total number of bytes eaten */ int32 lEat; /* number of bytes eaten on this item */ char * pCurrentPos; char * pBlock; HotlistStruct * pParent = HOT_GetHotlist(); if(!pOriginalBlock) return; /* make a copy of the string we can write into */ pCurrentPos = pBlock = (char *) XP_ALLOC(lTotalLen + 1); if(!pBlock) return; /* copy the data over and make sure we are NULL terminated to make life easier */ XP_MEMCPY(pBlock, pOriginalBlock, lTotalLen); pBlock[lTotalLen] = '\0'; /* * if our very first element is a header then we really want to insert * everything into the header and not after it --- I think. */ if(item && item->type == HOT_HeaderType) { pParent = item; item = NULL; /* * gack! if we are inserting under a header make sure its set up * to accept children */ if(!pParent->children) pParent->children = XP_ListNew(); } /* long format can have all kinds of different types of things in it */ if(bLongFormat) { while(lBytesEaten < lTotalLen) { /* determine the type of the next entry */ sVal = 0; XP_MEMCPY(&sVal, pCurrentPos, 2); pCurrentPos += 2; lBytesEaten += 2; switch(sVal) { case HOT_URLType: item = hot_read_URL(pCurrentPos, pParent, item, bLongFormat, &lEat); lBytesEaten += lEat; pCurrentPos += lEat; break; case HOT_HeaderType: item = hot_read_Header(pCurrentPos, pParent, item, bLongFormat, &lEat); lBytesEaten += lEat; pCurrentPos += lEat; break; case HOT_SeparatorType: item = hot_read_Separator(pCurrentPos, pParent, item, bLongFormat, &lEat); lBytesEaten += lEat; pCurrentPos += lEat; break; default: /* bogus type. Who knows whats going on. Just quit and get out */ return; break; } } } else { /* short format is just a list of URLs separated by \n's */ while(lBytesEaten < lTotalLen) { item = hot_read_URL(pCurrentPos, pParent, item, bLongFormat, &lEat); lBytesEaten += lEat; pCurrentPos += lEat; /* if we just walked over a \0 we are done */ if(pOriginalBlock[lBytesEaten - 1] == '\0') lBytesEaten = lTotalLen; } } /* mark the bookmark list as changed and clean up */ HOT_SetModified(); XP_FREE(pBlock); }
/* returns a unmalloced static string * that is only available for temporary use. */ PUBLIC char * xp_FileName (const char *name, XP_FileType type, char* buf, char* configBuf) { const char *conf_dir = xp_unix_config_directory(configBuf); switch (type) { case xpSARCacheIndex: { const char *sar_cache_dir = FE_SARCacheDir; if (!sar_cache_dir || !*sar_cache_dir) sar_cache_dir = conf_dir; if (sar_cache_dir [strlen (sar_cache_dir) - 1] == '/') sprintf (buf, "%.900sarchive.fat", sar_cache_dir); else sprintf (buf, "%.900s/archive.fat", sar_cache_dir); name = buf; break; } case xpSARCache: { /* WH_TempName() returns relative pathnames for the cache files, so that relative paths get written into the cacheFAT database. WH_FileName() converts them to absolute if they aren't already so that the logic of XP_FileOpen() and XP_FileRename() and who knows what else is simpler. */ if (name != NULL && *name == '/') break ; { char *tmp = FE_SARCacheDir; if (!tmp || !*tmp) tmp = "/tmp"; if (tmp [strlen (tmp) - 1] == '/') sprintf (buf, "%.500s%.500s", tmp, name); else sprintf (buf, "%.500s/%.500s", tmp, name); name = buf; } break; } case xpCacheFAT: { const char *cache_dir = FE_CacheDir; if (!cache_dir || !*cache_dir) cache_dir = conf_dir; if (cache_dir [strlen (cache_dir) - 1] == '/') sprintf (buf, "%.900sindex.db", cache_dir); else sprintf (buf, "%.900s/index.db", cache_dir); name = buf; break; } case xpCache: { /* WH_TempName() returns relative pathnames for the cache files, so that relative paths get written into the cacheFAT database. WH_FileName() converts them to absolute if they aren't already so that the logic of XP_FileOpen() and XP_FileRename() and who knows what else is simpler. */ if (*name != '/') { char *tmp = FE_CacheDir; if (!tmp || !*tmp) tmp = "/tmp"; if (tmp [strlen (tmp) - 1] == '/') sprintf (buf, "%.500s%.500s", tmp, name); else sprintf (buf, "%.500s/%.500s", tmp, name); name = buf; } break; } case xpHTTPCookie: { #ifndef OLD_UNIX_FILES sprintf (buf, "%.900s/cookies", conf_dir); #else /* OLD_UNIX_FILES */ sprintf (buf, "%.900s/.netscape-cookies", conf_dir); #endif /* OLD_UNIX_FILES */ name = buf; break; } case xpRegistry: { if ( name == NULL || *name == '\0' ) { #ifndef OLD_UNIX_FILES sprintf (buf, "%.900s/registry", conf_dir); #else /* OLD_UNIX_FILES */ sprintf (buf, "%.900s/.netscape-registry", conf_dir); #endif /* OLD_UNIX_FILES */ name = buf; } else { XP_ASSERT( name[0] == '/' ); } break; } case xpProxyConfig: { sprintf(buf, "%.900s/proxyconf", conf_dir); name = buf; break; } case xpTemporary: { if (*name != '/') { char *tmp = FE_TempDir; if (!tmp || !*tmp) tmp = "/tmp"; if (tmp [strlen (tmp) - 1] == '/') sprintf (buf, "%.500s%.500s", tmp, name); else sprintf (buf, "%.500s/%.500s", tmp, name); name = buf; } break; } case xpNewsRC: case xpSNewsRC: case xpTemporaryNewsRC: { /* In this case, `name' is "" or "host" or "host:port". */ char *home = getenv ("HOME"); const char *newsrc_dir = ((FE_UserNewsRC && *FE_UserNewsRC) ? FE_UserNewsRC : (home ? home : "")); const char *basename = (type == xpSNewsRC ? ".snewsrc" : ".newsrc"); const char *suffix = (type == xpTemporaryNewsRC ? ".tmp" : ""); if (*name) sprintf (buf, "%.800s%.1s%.8s-%.128s%.4s", newsrc_dir, (newsrc_dir[XP_STRLEN(newsrc_dir)-1] == '/' ? "" : "/"), basename, name, suffix); else sprintf (buf, "%.800s%.1s%.128s%.4s", newsrc_dir, (newsrc_dir[XP_STRLEN(newsrc_dir)-1] == '/' ? "" : "/"), basename, suffix); name = buf; break; } case xpNewsgroups: case xpSNewsgroups: { #ifndef OLD_UNIX_FILES sprintf (buf, "%.800s/%snewsgroups-%.128s", conf_dir, type == xpSNewsgroups ? "s" : "", name); #else /* OLD_UNIX_FILES */ sprintf (buf, "%.800s/.netscape-%snewsgroups-%.128s", conf_dir, type == xpSNewsgroups ? "s" : "", name); #endif /* OLD_UNIX_FILES */ name = buf; break; } case xpExtCacheIndex: #ifndef OLD_UNIX_FILES sprintf (buf, "%.900s/cachelist", conf_dir); #else /* OLD_UNIX_FILES */ sprintf (buf, "%.900s/.netscape-cache-list", conf_dir); #endif /* OLD_UNIX_FILES */ name = buf; break; case xpGlobalHistory: name = FE_GlobalHist; break; case xpCertDB: #ifndef OLD_UNIX_FILES if ( name ) { sprintf (buf, "%.900s/cert%s.db", conf_dir, name); } else { sprintf (buf, "%.900s/cert.db", conf_dir); } #else /* OLD_UNIX_FILES */ sprintf (buf, "%.900s/.netscape-certdb", conf_dir); #endif /* OLD_UNIX_FILES */ name = buf; break; case xpCertDBNameIDX: #ifndef OLD_UNIX_FILES sprintf (buf, "%.900s/cert-nameidx.db", conf_dir); #else /* OLD_UNIX_FILES */ sprintf (buf, "%.900s/.netscape-certdb-nameidx", conf_dir); #endif /* OLD_UNIX_FILES */ name = buf; break; case xpKeyDB: #ifndef OLD_UNIX_FILES if ( name ) { sprintf (buf, "%.900s/key%s.db", conf_dir, name); } else { sprintf (buf, "%.900s/key.db", conf_dir); } #else /* OLD_UNIX_FILES */ sprintf (buf, "%.900s/.netscape-keydb", conf_dir); #endif /* OLD_UNIX_FILES */ name = buf; break; case xpSecModuleDB: sprintf (buf, "%.900s/secmodule.db", conf_dir); name = buf; break; case xpSignedAppletDB: { #ifndef OLD_UNIX_FILES if ( name ) { sprintf (buf, "%.900s/signedapplet%s.db", conf_dir, name); } else { sprintf (buf, "%.900s./signedapplet.db", conf_dir); } #else /* OLD_UNIX_FILES */ sprintf (buf, "%.900s/.netscape-signedappletdb", conf_dir); #endif /* OLD_UNIX_FILES */ name = buf; break; } case xpFileToPost: case xpSignature: /* These are always absolute pathnames. * BUT, the user can type in whatever so * we can't assert if it doesn't begin * with a slash */ break; case xpExtCache: case xpKeyChain: case xpURL: case xpHotlist: case xpBookmarks: case xpMimeTypes: case xpSocksConfig: case xpMailFolder: #ifdef BSDI /* In bsdi, mkdir fails if the directory name is terminated * with a '/'. - dp */ if (name[strlen(name)-1] == '/') { strcpy(buf, name); buf[strlen(buf)-1] = '\0'; name = buf; } #endif #ifndef MCC_PROXY /* * These are always absolute pathnames for the Navigator. * Only the proxy (servers) may have pathnames relative * to their current working directory (the servers chdir * to their admin/config directory on startup. * */ if (name) XP_ASSERT (name[0] == '/'); #endif /* ! MCC_PROXY */ break; case xpMailFolderSummary: /* Convert /a/b/c/foo to /a/b/c/.foo.summary (note leading dot) */ { const char *slash; slash = strrchr (name, '/'); if (name) XP_ASSERT (name[0] == '/'); XP_ASSERT (slash); if (!slash) return 0; XP_MEMCPY (buf, name, slash - name + 1); buf [slash - name + 1] = '.'; XP_STRCPY (buf + (slash - name) + 2, slash + 1); XP_STRCAT (buf, ".summary"); name = buf; break; } case xpAddrBookNew: /* Convert foo.db to /a/b/c/foo.db */ { if ( name ) { sprintf (buf, "%.900s/%s", conf_dir, name); } else { sprintf (buf, "%.900s/abook.nab", conf_dir); } #if defined(DEBUG_tao) printf("\n xpAddrBookNew, xp_FileName, buf=%s\n", buf); #endif name = buf; break; } case xpAddrBook: /* Convert /a/b/c/foo to /a/b/c/foo.db (note leading dot) */ { /* Tao_27jan97 */ char *dot = NULL; int len = 0; const char *base = NULL; if (name) XP_ASSERT (name[0] == '/'); dot = XP_STRRCHR(name, '.'); if (dot) { len = dot - name + 1; XP_STRNCPY_SAFE(buf, name, len); }/* if */ XP_STRCAT (buf, ".nab"); /* Tao_02jun97 don't convert addrbook.db * reuse len, dot */ base = XP_STRRCHR(name, '/'); if (base && *base == '/') base++; #if defined(DEBUG_tao) printf("\n++++ xpAddrBook, before xp_FileName=%s\n", name); #endif if (!base || XP_STRCMP(base, "addrbook.db")) /* not old addrbook.db file */ name = buf; #if defined(DEBUG_tao) printf("\n xpAddrBook, xp_FileName=%s\n", name); #endif break; } case xpVCardFile: /* Convert /a/b/c/foo to /a/b/c/foo.vcf (note leading dot) */ { #if 1 /* Tao_27jan97 */ char *dot = NULL; int len = 0; if (name) XP_ASSERT (name[0] == '/'); dot = XP_STRRCHR(name, '.'); if (dot) { len = dot - name + 1; XP_STRNCPY_SAFE(buf, name, len); }/* if */ XP_STRCAT (buf, ".vcf"); name = buf; #if defined(DEBUG_tao_) printf("\n xp_FileName=%s\n", name); #endif #else const char *slash; slash = strrchr (name, '/'); if (name) XP_ASSERT (name[0] == '/'); XP_ASSERT (slash); if (!slash) return 0; XP_MEMCPY (buf, name, slash - name + 1); XP_STRCAT (buf, ".vcf"); name = buf; #endif break; } case xpLDIFFile: /* Convert /a/b/c/foo to /a/b/c/foo.ldif (note leading dot) */ { #if 1 /* Tao_27jan97 */ char *dot = NULL; int len = 0; if (name) XP_ASSERT (name[0] == '/'); dot = XP_STRRCHR(name, '.'); if (dot) { len = dot - name + 1; XP_STRNCPY_SAFE(buf, name, len); }/* if */ XP_STRCAT (buf, ".ldif"); name = buf; #if defined(DEBUG_tao_) printf("\n xp_FileName=%s\n", name); #endif #else const char *slash; slash = strrchr (name, '/'); if (name) XP_ASSERT (name[0] == '/'); XP_ASSERT (slash); if (!slash) return 0; XP_MEMCPY (buf, name, slash - name + 1); XP_STRCAT (buf, ".ldif"); name = buf; #endif break; } case xpJSMailFilters: sprintf(buf, "%.900s/filters.js", conf_dir); name = buf; break; case xpJSHTMLFilters: sprintf(buf, "%.900s/hook.js", conf_dir); name = buf; break; case xpNewsSort: sprintf(buf, "%.800s/xover-cache/%.128snetscape-newsrule", conf_dir, name); break; case xpMailSort: #ifndef OLD_UNIX_FILES sprintf(buf, "%.900s/mailrule", conf_dir); #else /* OLD_UNIX_FILES */ sprintf(buf, "%.900s/.netscape-mailrule", conf_dir); #endif /* OLD_UNIX_FILES */ name = buf; break; case xpMailPopState: #ifndef OLD_UNIX_FILES sprintf(buf, "%.900s/popstate", conf_dir); #else /* OLD_UNIX_FILES */ sprintf(buf, "%.900s/.netscape-popstate", conf_dir); #endif /* OLD_UNIX_FILES */ name = buf; break; case xpMailFilterLog: sprintf(buf, "%.900s/.netscape-mailfilterlog", conf_dir); name = buf; break; case xpNewsFilterLog: sprintf(buf, "%.900s/.netscape-newsfilterlog", conf_dir); name = buf; break; case xpMailSubdirectory: { char * pEnd = strrchr(name, '/'); strcpy(buf, name); /* strip off the extension */ if(!pEnd) pEnd = buf; pEnd = strchr(pEnd, '.'); if(pEnd) *pEnd = '\0'; strcat(buf, ".sbd/"); name = buf; } break; case xpXoverCache: sprintf(buf, "%.800s/xover-cache/%.128s", conf_dir, name); name = buf; break; case xpNewsHostDatabase: sprintf(buf, "%.800s/newsdb", conf_dir); name = buf; break; case xpImapRootDirectory: { char prefbuf[1024]; int len = sizeof prefbuf / sizeof *prefbuf; if ((PREF_GetCharPref("mail.imap.root_dir", prefbuf, &len) == PREF_NOERROR) && *prefbuf == '/') /* guard against assert: line 806, file xp_file.c */ XP_STRNCPY_SAFE(buf, prefbuf, len); /* Copy back to the buffer that was passed in. * We couldn't have PREF_GetCharPref() just put it there * initially because the size of buf wasn't passed in * (it happens to be 1024) and PREF_GetCharPref() insists * on having a size. Sigh. */ else { char *home = getenv ("HOME"); sprintf(buf, "%s/ns_imap", (home ? home : "")); } name = buf; break; } case xpImapServerDirectory: { char prefbuf[1024]; int len = sizeof prefbuf / sizeof *prefbuf; if ((PREF_GetCharPref("mail.imap.root_dir", prefbuf, &len) == PREF_NOERROR) && *prefbuf == '/') /* guard against assert: line 806, file xp_file.c */ sprintf(buf, "%s/%s", prefbuf, name); else { char *home = getenv ("HOME"); sprintf(buf, "%s/ns_imap/%s", (home ? home : ""), name); } name = buf; break; } case xpFolderCache: sprintf (buf, "%s/summary.dat", conf_dir); name = buf; break; case xpCryptoPolicy: { extern void fe_GetProgramDirectory(char *path, int len); char *policyFN = "moz40p3"; char *mozHome = getenv("MOZILLA_HOME"); char *lang = getenv("LANG"); int result; char dirName[1024]; name = buf; if (!xp_unix_sprintf_stat(buf, conf_dir, lang, policyFN)) break; if (!xp_unix_sprintf_stat(buf, mozHome, lang, policyFN)) break; fe_GetProgramDirectory(dirName, sizeof dirName); if (!xp_unix_sprintf_stat(buf, dirName, lang, policyFN)) break; /* couldn't find it, but must leave a valid file name in buf */ sprintf(buf, "%.900s/%s", conf_dir, policyFN); break; } case xpPKCS12File: /* Convert /a/b/c/foo to /a/b/c/foo.p12 (note leading dot) */ { int len = 0; if(name) { XP_ASSERT(name[0] == '/'); /* only append if there is enough space in the buffer */ /* this should be changed if the size of the buf changes */ if((XP_STRLEN(name) + 4) <= 1020) { /* include NULL in length */ len = XP_STRLEN(name) + 1; XP_STRNCPY_SAFE(buf, name, len); /* we want to concatenate ".p12" if it is not the * last 4 characters of the name already. * If len is less than 5 (including the terminating * NULL), it is not ".p12". * If the len is > 5 it may have the .p12, so we want * to check and only append .p12 if the name * specified does not end in .p12. * only side effect -- this allows for the filename * ".p12" which is fine. */ if((len >= 5) && XP_STRCASECMP(&(name[len-4-1]), ".p12")) { XP_STRCAT(buf, ".p12"); } else if(len < 5) { /* can't be ".p12", so we append ".p12" */ XP_STRCAT(buf, ".p12"); } name = buf; } } break; } case xpJSCookieFilters: { sprintf(buf, "%.900s/cookies.js", conf_dir); name = buf; break; } case xpLIPrefs: { sprintf(buf, "%.900s/liprefs.js", conf_dir); name = buf; break; } default: abort (); } return (char *) name; }
/* * Write out a boring URL hotlist entry. See comment at the top of * hot_measure_URL for the format used. Assume we start writing at * the start of the buffer passed in. Return a pointer to where the * buffer ends when we get done. */ PRIVATE char * hot_write_URL(char * buffer, HotlistStruct * item, int bLongFormat, int nIndent) { int iLen; int32 lVal; int32 sVal; if(!item || !buffer) return(buffer); if(bLongFormat) { /* copy the type */ sVal = (int16) item->type; iLen = 2; XP_MEMCPY(buffer, &sVal, iLen); buffer += iLen; /* copy the name */ if(item->name) { iLen = XP_STRLEN(item->name); XP_MEMCPY(buffer, item->name, iLen); buffer += iLen; } /* put the \n terminator on */ *buffer++ = '\n'; /* copy the address */ if(item->address) { iLen = XP_STRLEN(item->address); XP_MEMCPY(buffer, item->address, iLen); buffer += iLen; } /* put the \n terminator on */ *buffer++ = '\n'; /* addition date */ lVal = (int32) item->addition_date; iLen = 4; XP_MEMCPY(buffer, &lVal, iLen); buffer += iLen; /* last visit date */ lVal = (int32) item->last_visit; iLen = 4; XP_MEMCPY(buffer, &lVal, iLen); buffer += iLen; /* copy the description */ if(item->description) { iLen = XP_STRLEN(item->description); XP_MEMCPY(buffer, item->description, iLen); buffer += iLen; } /* put the \n terminator on */ *buffer++ = '\0'; } else { XP_MEMSET(buffer, ' ', nIndent); buffer += nIndent; if(item->address) { XP_STRCPY(buffer, item->address); buffer += XP_STRLEN(item->address); } *buffer++ = '\n'; } return(buffer); }
void drawScoreBoard( BoardCtxt* board ) { if ( board->scoreBoardInvalid ) { XP_U16 ii; XP_U16 nPlayers = board->gi->nPlayers; DrawFocusState dfs = dfsFor( board, OBJ_SCORE ); ScoresArray scores; ModelCtxt* model = board->model; XP_S16 nTilesInPool = server_countTilesInPool( board->server ); if ( board->gameOver ) { model_figureFinalScores( model, &scores, NULL ); } else { for ( ii = 0; ii < nPlayers; ++ii ) { scores.arr[ii] = model_getPlayerScore( model, ii ); } } if ( draw_scoreBegin( board->draw, &board->scoreBdBounds, nPlayers, scores.arr, nTilesInPool, dfs ) ) { XP_S16 curTurn = server_getCurrentTurn( board->server ); XP_U16 selPlayer = board->selPlayer; XP_Rect scoreRect; XP_Rect playerRects[nPlayers]; XP_U16 remDim; XP_Bool isVertical = !board->scoreSplitHor; XP_Bool remFocussed = XP_FALSE; XP_Bool focusAll = XP_FALSE; DrawScoreInfo data[nPlayers]; #ifdef KEYBOARD_NAV XP_S16 cursorIndex = -1; if ( (board->focussed == OBJ_SCORE) && !board->hideFocus ) { focusAll = !board->focusHasDived; if ( !focusAll ) { cursorIndex = board->scoreCursorLoc; remFocussed = CURSOR_LOC_REM == cursorIndex; --cursorIndex; } } #endif XP_MEMSET( playerRects, 0, sizeof(playerRects) ); XP_MEMSET( data, 0, sizeof(data) ); scoreRect = board->scoreBdBounds; if ( !draw_drawRemText( board->draw, nTilesInPool, focusAll || remFocussed, &scoreRect ) ) { scoreRect.height = scoreRect.width = 0; } XP_ASSERT( rectContainsRect( &board->scoreBdBounds, &scoreRect ) ); remDim = isVertical? scoreRect.height : scoreRect.width; board->remDim = remDim; #ifdef KEYBOARD_NAV board->remRect = scoreRect; if ( 0 == remDim && board->scoreCursorLoc == CURSOR_LOC_REM ) { board->scoreCursorLoc = selPlayer + 1; } #endif scoreRect = board->scoreBdBounds; if ( isVertical ) { scoreRect.height -= remDim; scoreRect.top += remDim; } else { scoreRect.width -= remDim; scoreRect.left += remDim; } for ( ii = 0; ii < nPlayers; ++ii ) { DrawScoreInfo* dsi = &data[ii]; LocalPlayer* lp = &board->gi->players[ii]; dsi->lsc = board_ScoreCallback; dsi->lscClosure = model; #ifdef KEYBOARD_NAV if ( (ii == cursorIndex) || focusAll ) { dsi->flags |= CELL_ISCURSOR; } #endif dsi->playerNum = ii; dsi->totalScore = scores.arr[ii]; dsi->isTurn = (ii == curTurn); dsi->name = emptyStringIfNull(lp->name); dsi->selected = board->trayVisState != TRAY_HIDDEN && ii==selPlayer; dsi->isRobot = LP_IS_ROBOT(lp); dsi->isRemote = !lp->isLocal; dsi->nTilesLeft = (nTilesInPool > 0)? -1: model_getNumTilesTotal( model, ii ); } draw_score_drawPlayers( board->draw, &scoreRect, nPlayers, data, playerRects ); for ( ii = 0; ii < nPlayers; ++ii ) { XP_Rect* rp = &playerRects[ii]; board->pti[ii].scoreDims = isVertical ? rp->height : rp->width; #ifdef KEYBOARD_NAV XP_MEMCPY( &board->pti[ii].scoreRects, rp, sizeof(board->pti[ii].scoreRects) ); #endif } draw_objFinished( board->draw, OBJ_SCORE, &board->scoreBdBounds, dfs ); board->scoreBoardInvalid = XP_FALSE; } } drawTimer( board ); } /* drawScoreBoard */
static XP_Bool dragDropContinueImpl( BoardCtxt* board, XP_U16 xx, XP_U16 yy, XP_U16 offset, XP_Bool scrollBoard, BoardObjectType* onWhichP ) { XP_Bool moving = XP_FALSE; DragObjInfo newInfo; DragState* ds = &board->dragState; XP_Bool draw = XP_FALSE; #ifdef XWFEATURE_RAISETILE yy -= ds->yyAdd; #endif if ( ds->dtype == DT_TILE ){ // Offset tiles being dragged so they are easier to see. yy -= offset; } (void)pointOnSomething( board, xx, yy, &newInfo.obj ); if ( !!onWhichP ) { *onWhichP = newInfo.obj; } if ( newInfo.obj == OBJ_BOARD ) { (void)coordToCell( board, xx, yy, &newInfo.u.board.col, &newInfo.u.board.row ); #ifdef XWFEATURE_CROSSHAIRS if ( !board->hideCrosshairs ) { draw = crosshairs_set( board, newInfo.u.board.col, newInfo.u.board.row ); } #endif } if ( ds->dtype == DT_DIVIDER ) { if ( OBJ_TRAY == newInfo.obj ) { XP_U16 newloc; XP_U16 scale = board->trayScaleH; xx -= board->trayBounds.left; newloc = xx / scale; if ( (xx % scale) > ((scale+board->dividerWidth)/2)) { ++newloc; } moving = dividerMoved( board, newloc ); } #ifdef XWFEATURE_SEARCHLIMIT } else if ( ds->dtype == DT_HINTRGN && newInfo.obj != OBJ_BOARD ) { /* do nothing */ #endif } else if ( ds->dtype == DT_BOARD ) { if ( newInfo.obj == OBJ_BOARD ) { XP_S16 diff = newInfo.u.board.col - ds->cur.u.board.col; if ( !ds->cellChanged && 0 != diff ) { ds->cellChanged = XP_TRUE; } diff /= SCROLL_DRAG_THRESHHOLD; moving = adjustXOffset( board, diff ); diff = newInfo.u.board.row - ds->cur.u.board.row; if ( !ds->cellChanged && 0 != diff ) { ds->cellChanged = XP_TRUE; } diff /= SCROLL_DRAG_THRESHHOLD; moving = adjustYOffset( board, diff ) || moving; } } else if ( ds->dtype == DT_TILE ) { if ( newInfo.obj == OBJ_BOARD ) { moving = (newInfo.u.board.col != ds->cur.u.board.col) || (newInfo.u.board.row != ds->cur.u.board.row) || (OBJ_TRAY == ds->cur.obj); } else if ( newInfo.obj == OBJ_TRAY ) { XP_Bool onDivider; XP_S16 index = pointToTileIndex( board, xx, yy, &onDivider ); if ( !onDivider ) { if ( index < 0 ) { /* negative means onto empty part of tray. Force left. */ index = model_getNumTilesInTray( board->model, board->selPlayer ); if ( OBJ_TRAY == ds->start.obj ) { --index; /* dragging right into space */ } } moving = (OBJ_BOARD == ds->cur.obj) || (index != ds->cur.u.tray.index); if ( moving ) { newInfo.u.tray.index = index; } } } if ( moving ) { if ( ds->dtype == DT_TILE ) { invalDragObjRange( board, &ds->cur, &newInfo ); #ifdef XWFEATURE_SEARCHLIMIT } else if ( ds->dtype == DT_HINTRGN ) { invalHintRectDiffs( board, &ds->cur, &newInfo ); if ( !ds->didMove ) { /* first time through */ invalCurHintRect( board, board->selPlayer ); } #endif } XP_MEMCPY( &ds->cur, &newInfo, sizeof(ds->cur) ); startScrollTimerIf( board, scrollBoard ); } } else { XP_ASSERT( 0 ); } // Change? if (mBoardScrollOn != scrollBoard){ // Yes, need this extra kick to get board scrolling going. startScrollTimerIf( board, scrollBoard ); // Only do once. mBoardScrollOn = scrollBoard; } if ( moving ) { draw = XP_TRUE; if ( !ds->didMove ) { /* This is the first time we've moved!!! Kill any future timers, and if there's a window up kill it.*/ board->penTimerFired = XP_FALSE; #ifdef XWFEATURE_MINIWIN if ( valHintMiniWindowActive( board ) ) { hideMiniWindow( board, XP_TRUE, MINIWINDOW_VALHINT ); } #endif ds->didMove = XP_TRUE; // Don't scroll right away; wait until tile touches edge of board. mBoardScrollOn = XP_FALSE; } } return draw; } /* dragDropContinueImpl */