void DataServeriOS::PerformRequestedCommand() { // Check password and initiate requested command if (strcmp(_pass,pass)==0) { // Password is correct if (strcmp(cmd,"digitalWrite")==0) { // Check if custom functions are requered, check if required for this port if (_cf && InArray(_CFPorts,_nCFports,atoi(port))) CallCustomFunction(); else RemoteDigitalWrite(); } else if (strcmp(cmd,"PWMWrite")==0) RemotePWMWrite(); else JSON_send(cmd); } else { // Password was incorrect _server->println("{\"arduino_io\":{\"ERROR\":\"007\"}}"); //ERROR 007; incorrect password } }
void DataServeriOS::JSON_send(char* command) { // Send requested information String bffr = "{\"arduino_io\":{"; char temp[128]; // If used on a UNO or equivalent if (strcmp(_Arduino, "UNO")==0) { // ReadAll if (strcmp(command,"ReadAll")==0) { // Analog bffr+="\"an\":{"; for (int i=0;i<=4;i++) { if (_cr && InArray(_CRPorts,_nCRports,i)) sprintf(temp,"\"a%d\":\"%s\",",i,_returnAnalogForPort(i)); else sprintf(temp,"\"a%d\":%d,",i,analogRead(i)); bffr+=String(temp); } if (_cr && InArray(_CRPorts,_nCRports,5)) sprintf(temp,"\"a%d\":\"%s\"",5,_returnAnalogForPort(5)); else sprintf(temp,"\"a%d\":%d}",5,analogRead(5)); bffr+=String(temp); if (_serial) Serial.print(bffr); _server->print(bffr); // Digital bffr=",\"di\":{"; for (int i=0;i<=8;i++) { if (_pwm && InArray(_PWMPorts,_nPWMports,i)) sprintf(temp,"\"d%d\":\"p%d\",",i,ValueForPWMPort(i)); else if (_cf && InArray(_CFPorts,_nCFports,i)) sprintf(temp,"\"d%d\":%s,",i,_returnDigitalForPort(i)); else sprintf(temp,"\"d%d\":%d,",i,digitalRead(i)); bffr+=String(temp); } if (_pwm && InArray(_PWMPorts,_nPWMports,9)) sprintf(temp,"\"d%d\":\"p%d\"}",9,ValueForPWMPort(9)); else if (_cf && InArray(_CFPorts,_nCFports,9)) sprintf(temp,"\"d%d\":%s,",9,_returnDigitalForPort(9)); else sprintf(temp,"\"d%d\":%d}",9,digitalRead(9)); bffr+=String(temp); bffr+="}}"; if (_serial) Serial.println(bffr); _server->println(bffr); } // PWMWrite else if (strcmp(command,"PWMWrite")==0) { bffr+="\"di\":{"; sprintf(temp,"\"d%d\":\"p%d\"}",atoi(port),ValueForPWMPort(atoi(port))); bffr+=String(temp); bffr+="}"; if (_serial) Serial.println(bffr); _server->println(bffr); } else _server->println("{\"arduino_io\":{\"ERROR\":\"006\"}}"); //ERROR 006; unknown command } // If used on a MEGA or equivalent else if (strcmp(_Arduino,"MEGA")==0) { if (strcmp(command,"ReadAll")==0) { // Analog bffr+="\"an\":{"; for (int i=0;i<=14;i++) { if (_cr && InArray(_CRPorts,_nCRports,i)) sprintf(temp,"\"a%d\":\"%s\",",i,_returnAnalogForPort(i)); else sprintf(temp,"\"a%d\":%d,",i,analogRead(i)); bffr+=String(temp); } if (_cr && InArray(_CRPorts,_nCRports,15)) sprintf(temp,"\"a%d\":\"%s\"",15,_returnAnalogForPort(15)); else sprintf(temp,"\"a%d\":%d}",15,analogRead(15)); bffr+=String(temp); if (_serial) Serial.print(bffr); _server->print(bffr); // Digital bffr=",\"di\":{"; for (int i=0;i<=9;i++) { if (_pwm && InArray(_PWMPorts,_nPWMports,i)) sprintf(temp,"\"d%d\":\"p%d\",",i,ValueForPWMPort(i)); else if (_cf && InArray(_CFPorts,_nCFports,i)) sprintf(temp,"\"d%d\":%s,",i,_returnDigitalForPort(i)); else sprintf(temp,"\"d%d\":%d,",i,digitalRead(i)); bffr+=String(temp); } for (int i=14;i<=52;i++) { if (_pwm && InArray(_PWMPorts,_nPWMports,i)) sprintf(temp,"\"d%d\":\"p%d\",",i,ValueForPWMPort(i)); else if (_cf && InArray(_CFPorts,_nCFports,i)) sprintf(temp,"\"d%d\":%s,",i,_returnDigitalForPort(i)); else sprintf(temp,"\"d%d\":%d,",i,digitalRead(i)); bffr+=String(temp); } if (_pwm && InArray(_PWMPorts,_nPWMports,53)) sprintf(temp,"\"d%d\":\"p%d\"}",53,ValueForPWMPort(53)); else if (_cf && InArray(_CFPorts,_nCFports,53)) sprintf(temp,"\"d%d\":%s,",53,_returnDigitalForPort(53)); else sprintf(temp,"\"d%d\":%d}",53,digitalRead(53)); bffr+=String(temp); bffr+="}}"; if (_serial) Serial.println(bffr); _server->println(bffr); } // PWMWrite else if (strcmp(command,"PWMWrite")==0) { bffr+="\"di\":{"; sprintf(temp,"\"d%d\":\"p%d\"}",atoi(port),ValueForPWMPort(atoi(port))); bffr+=String(temp); bffr+="}"; if (_serial) Serial.println(bffr); _server->println(bffr); } else _server->println("{\"arduino_io\":{\"ERROR\":\"006\"}}"); //ERROR 006; unknown command } bffr=""; }
void Piano::DrawGL(int off) { unsigned int w = cc1->GetClientSize().x, h = GetHeight(), endx = 0; if(m_tex_piano_height != h) BuildGLTexture(); int y1 = off, y2 = y1 + h; int nKeys = m_key_array.GetCount(); // we could cache the coordinates and recompute only when the piano hash changes, // but the performance is already fast enough at this point float *texcoords = new float[(nKeys*3+1)*4*2], *coords = new float[(nKeys*3+1)*4*2]; int tc = 0, vc = 0; // draw the keys for( int i = 0; i < nKeys; i++ ) { int key_db_index = m_key_array.Item( i ); int b; if( ChartData->GetDBChartType( key_db_index ) == CHART_TYPE_CM93 || ChartData->GetDBChartType( key_db_index ) == CHART_TYPE_CM93COMP ) b = 0; else if( ChartData->GetDBChartFamily( key_db_index ) == CHART_FAMILY_VECTOR ) b = 2; else // Raster Chart b = 4; if(!InArray(m_active_index_array, key_db_index)) b++; wxRect box = KeyRect.Item( i ); float y = h*b, v1 = (y+.5)/m_texh, v2 = (y+h-.5)/m_texh; // u contains the pixel coordinates in the texture for the three possible rectangles const float u[3][6] = {{0, 3, 4, 4, 5, 8}, {9, 14, 15, 15, 18, 23}, {24, 31, 32, 32, 34, 41}}; int uindex; if(m_brounded) { if(InArray(m_eclipsed_index_array, key_db_index)) uindex = 2; else uindex = 1; } else uindex = 0; // if the chart is too narrow.. we maybe render the "wrong" rectangle because it can be thinner int x1 = box.x, x2 = x1+box.width, w = 2*uindex+1; while(x1 + w > x2 - w && uindex > 0) uindex--, w -= 2; // the minimal width rectangles are texture mapped to the // width needed by mapping 3 quads: left middle and right const int x[6] = {x1 - 3, x1 + w, x2 - w, x2+3}; for(int i=0; i<3; i++ ) { float u1 = (u[uindex][2*i]+.5)/m_texw, u2 = (u[uindex][2*i+1]+.5)/m_texw; int x1 = x[i], x2 = x[i+1]; texcoords[tc++] = u1, texcoords[tc++] = v1, coords[vc++] = x1, coords[vc++] = y1; texcoords[tc++] = u2, texcoords[tc++] = v1, coords[vc++] = x2, coords[vc++] = y1; texcoords[tc++] = u2, texcoords[tc++] = v2, coords[vc++] = x2, coords[vc++] = y2; texcoords[tc++] = u1, texcoords[tc++] = v2, coords[vc++] = x1, coords[vc++] = y2; } endx = x[3]; } // if not transparent, fill the rest of the chart bar with the background ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle(); if(!style->chartStatusWindowTransparent && endx < w) { texcoords[tc++] = 0, texcoords[tc++] = 0, coords[vc++] = endx, coords[vc++] = y1; texcoords[tc++] = 0, texcoords[tc++] = 0, coords[vc++] = w, coords[vc++] = y1; texcoords[tc++] = 0, texcoords[tc++] = 0, coords[vc++] = w, coords[vc++] = y2; texcoords[tc++] = 0, texcoords[tc++] = 0, coords[vc++] = endx, coords[vc++] = y2; } glBindTexture(GL_TEXTURE_2D, m_tex); if(style->chartStatusWindowTransparent) { glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glColor4ub(255, 255, 255, 200); // perhaps we could allow the style to set this glEnable(GL_BLEND); } else glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); glEnable(GL_TEXTURE_2D); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, texcoords); glVertexPointer(2, GL_FLOAT, 0, coords); glDrawArrays(GL_QUADS, 0, vc/2); // draw the bitmaps vc = tc = 0; for( int i = 0; i < nKeys; i++ ) { int key_db_index = m_key_array.Item( i ); if( -1 == key_db_index ) continue; wxRect box = KeyRect.Item( i ); wxBitmap *bitmaps[] = {m_pInVizIconBmp, m_pTmercIconBmp, m_pSkewIconBmp, m_pPolyIconBmp}; int index; if(InArray(m_noshow_index_array, key_db_index)) index = 0; else { if(InArray(m_skew_index_array, key_db_index)) index = 2; else if(InArray(m_tmerc_index_array, key_db_index)) index = 1; else if(InArray(m_poly_index_array, key_db_index)) index = 3; else continue; } int x1, y1, iw = bitmaps[index]->GetWidth(), ih = bitmaps[index]->GetHeight(); if(InArray(m_noshow_index_array, key_db_index)) x1 = box.x + 4, y1 = box.y + 3; else x1 = box.x + box.width - iw - 4, y1 = box.y + 2; y1 += off; int x2 = x1 + iw, y2 = y1 + ih; wxBrush brushes[] = { m_scBrush, m_cBrush, m_svBrush, m_vBrush, m_slBrush, m_tBrush, m_uvBrush }; float yoff = ((sizeof brushes) / (sizeof *brushes))*h + 16*index; float u1 = 0, u2 = (float)iw / m_texw; float v1 = yoff / m_texh, v2 = (yoff + ih) / m_texh; texcoords[tc++] = u1, texcoords[tc++] = v1, coords[vc++] = x1, coords[vc++] = y1; texcoords[tc++] = u2, texcoords[tc++] = v1, coords[vc++] = x2, coords[vc++] = y1; texcoords[tc++] = u2, texcoords[tc++] = v2, coords[vc++] = x2, coords[vc++] = y2; texcoords[tc++] = u1, texcoords[tc++] = v2, coords[vc++] = x1, coords[vc++] = y2; } glEnable(GL_BLEND); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); glTexCoordPointer(2, GL_FLOAT, 0, texcoords); glVertexPointer(2, GL_FLOAT, 0, coords); glDrawArrays(GL_QUADS, 0, vc/2); glDisable(GL_BLEND); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); delete [] texcoords; delete [] coords; glDisable(GL_TEXTURE_2D); }
void Piano::DrawGL(int off) { OCPNStopWatch sw; int w = cc1->GetClientSize().x, h = GetHeight(); printf("t0: %f\n", sw.Time()); glBindTexture(GL_TEXTURE_2D, m_tex); ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle(); if(style->chartStatusWindowTransparent) { glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glColor4ub(255, 255, 255, 200); // perhaps we could allow the style to set this glEnable(GL_BLEND); } else glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); for(int i=0; i<30; i++) { glTexCoord2f(0, 0), glVertex2f(0, off); glTexCoord2f(m_texcoords[0], 0), glVertex2f(w, off); glTexCoord2f(m_texcoords[0], m_texcoords[1]), glVertex2f(w, off+h); glTexCoord2f(0, m_texcoords[1]), glVertex2f(0, off+h); } glEnd(); printf("t1: %f\n", sw.Time()); int iw = 9, ih = 13; if(!m_icontex) { glGenTextures( 1, &m_icontex ); glBindTexture(GL_TEXTURE_2D, m_icontex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); iw = m_pPolyIconBmp->GetWidth(); ih = m_pPolyIconBmp->GetHeight(); wxImage im = m_pPolyIconBmp->ConvertToImage(); unsigned char *data = new unsigned char[4*iw*ih], *d = data, *e = im.GetData(), *a = im.GetAlpha(); for(int i=0; i<iw*ih; i++) { memcpy(d, e, 3), d+=3, e+=3; *d = *a, d++, a++; } glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, iw, ih, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); delete [] data; } printf("t2: %f\n", sw.Time()); glBindTexture(GL_TEXTURE_2D, m_icontex); glEnable(GL_BLEND); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); printf("t3: %f\n", sw.Time()); glBegin(GL_QUADS); int nKeys = m_key_array.GetCount(); // draw the bitmaps for( int i = 0; i < nKeys; i++ ) { int key_db_index = m_key_array.Item( i ); if( -1 == key_db_index ) continue; wxRect box = KeyRect.Item( i ); float u1 = 0, u2 = 1, v = 1; int x1, y1; if(InArray(m_noshow_index_array, key_db_index)) x1 = box.x + 4, y1 = box.y + 3; else { x1 = box.x + box.width - iw - 4, y1 = box.y + 2; if(InArray(m_skew_index_array, key_db_index)) ; else if(InArray(m_tmerc_index_array, key_db_index)) ; else if(InArray(m_poly_index_array, key_db_index)) ; else continue; } y1 += off; int x2 = x1 + iw, y2 = y1 + ih; glTexCoord2f(u1, 0), glVertex2i(x1, y1); glTexCoord2f(u2, 0), glVertex2i(x2, y1); glTexCoord2f(u2, v), glVertex2i(x2, y2); glTexCoord2f(u1, v), glVertex2i(x1, y2); } glEnd(); printf("t4: %f\n", sw.Time()); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); }
// but requires updating the texture if the piano changes which is slower (although still quite fast) // the other problem is the code is difficult to follow and maintain // can remove this when we know we aren't going to ever be using it void Piano::UpdateGLTexture() { extern GLenum g_texture_rectangle_format; int w = cc1->GetClientSize().x, h = GetHeight(), tex_w, tex_h; if(g_texture_rectangle_format == GL_TEXTURE_2D) tex_w = w, tex_h = h; else tex_w = NextPow2(w), tex_h = NextPow2(h); m_texcoords[0] = (float)w / tex_w; m_texcoords[1] = (float)h / tex_h; // this isn't very pretty but should at least be fast enough unsigned char bgcolor[4], tbgcolor[4]; SetColor(bgcolor, m_backBrush); SetColor(tbgcolor, m_backBrush); wxColour b = GetGlobalColor( _T("CHBLK") ); unsigned char bcolor[4] = {b.Red(), b.Green(), b.Blue(), 255}; ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle(); if(style->chartStatusWindowTransparent) tbgcolor[3] = 0; unsigned char *data = new unsigned char[4*w*h]; // fill to background color for(int x = 0; x < w; x++) { unsigned char *pos = data + 4*x; memcpy(pos, tbgcolor, 4); } for(int y = 1; y < 8; y++) { unsigned char *pos = data + 4*(y*w); memcpy(pos, data, 4*w); } int nKeys = m_key_array.GetCount(); // draw the keys for( int i = 0; i < nKeys; i++ ) { int key_db_index = m_key_array.Item( i ); if( -1 == key_db_index ) continue; bool selected = InArray(m_active_index_array, key_db_index); unsigned char color[4]; if( ChartData->GetDBChartType( key_db_index ) == CHART_TYPE_CM93 || ChartData->GetDBChartType( key_db_index ) == CHART_TYPE_CM93COMP ) { if(selected) SetColor(color, m_scBrush ); else SetColor(color, m_cBrush ); } else if( ChartData->GetDBChartFamily( key_db_index ) == CHART_FAMILY_VECTOR ) { if(selected) SetColor(color, m_svBrush ); else SetColor(color, m_vBrush ); } else { // Raster Chart if(selected) SetColor(color, m_slBrush ); else SetColor(color, m_tBrush ); } #if 0 // Check to see if this box appears in the sub_light array // If so, add a crosshatch pattern to the brush if(InArray(m_eclipsed_index_array, key_db_index)) { wxBrush ebrush( dc.GetBrush().GetColour(), wxCROSSDIAG_HATCH ); dc.SetBrush(ebrush); } #endif if(m_bBusy) SetColor(color, m_uvBrush ); wxRect box = KeyRect.Item( i ); bool eclipsed = InArray(m_eclipsed_index_array, key_db_index); int sympoint = m_brounded ? (eclipsed ? 5 : 3) : 1; for(int y = 0; y < 6; y++) { unsigned char *pos = data + 4*((box.y+y)*w + box.x); if(y > sympoint) { int line; if(y < box.height - sympoint) line = sympoint; else line = box.height-y-1; // shouldn't hit memcpy(pos, data + 4*((box.y+line)*w + box.x), 4*box.width); continue; } for(int x = 0; x < box.width; x++, pos+=4) { if(y == 0) { if( m_brounded && (x <= 2 || x >= box.width - 3) ) memcpy(pos, tbgcolor, 4); else memcpy(pos, bcolor, 4); } else if(m_brounded) { if(y == 1) { if(x == 0 || x == box.width - 1) memcpy(pos, tbgcolor, 4); else if(x == 1 || x == 2 || x == box.width - 3 || x == box.width - 2) memcpy(pos, bcolor, 4); else memcpy(pos, color, 4); } else if(y == 2) { if(x == 0 || x == box.width - 1) memcpy(pos, tbgcolor, 4); else if(x == 1 || x == box.width - 2) memcpy(pos, bcolor, 4); else memcpy(pos, color, 4); } else if(eclipsed) { if(x == 0 || x == box.width - 1) memcpy(pos, bcolor, 4); else { if(y == 3) { if(x <= 4 || x >= box.width - 5) memcpy(pos, color, 4); else memcpy(pos, bcolor, 4); } else if(y == 4) { if(x <= 3 || x >= box.width - 4) memcpy(pos, color, 4); else if(x == 4 || x == box.width - 5) memcpy(pos, bcolor, 4); else memcpy(pos, bgcolor, 4); } else { if(x <= 2 || x >= box.width - 3) memcpy(pos, color, 4); else if(x == 3 || x == box.width - 4) memcpy(pos, bcolor, 4); else memcpy(pos, bgcolor, 4); } } } else goto def; } else { def: if(x == 0 || x == box.width - 1) memcpy(pos, bcolor, 4); else memcpy(pos, color, 4); } } } } // quickly fill the rest via symmetry for(int y = 8; y < h; y++) { int line; if(y < h - 7) line = 7; else line = h-y-1; memcpy(data + 4*(y*w), data + 4*(line*w), 4*w); } if(!m_tex) glGenTextures( 1, &m_tex ); glBindTexture(GL_TEXTURE_2D, m_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if(g_texture_rectangle_format == GL_TEXTURE_2D) glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); else { glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 ); glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data ); } delete [] data; }
void Piano::Paint( int y, ocpnDC& dc, wxDC *shapeDC ) { if(shapeDC) { shapeDC->SetBackground( *wxBLACK_BRUSH); shapeDC->SetBrush( *wxWHITE_BRUSH); shapeDC->SetPen( *wxWHITE_PEN); shapeDC->Clear(); } ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle(); if(!style->chartStatusWindowTransparent) { dc.SetPen( *wxTRANSPARENT_PEN ); dc.SetBrush( m_backBrush ); dc.DrawRectangle( 0, y, cc1->GetClientSize().x, GetHeight() ); } // Create the Piano Keys int nKeys = m_key_array.GetCount(); wxPen ppPen( GetGlobalColor( _T("CHBLK") ), 1, wxPENSTYLE_SOLID ); dc.SetPen( ppPen ); for( int i = 0; i < nKeys; i++ ) { int key_db_index = m_key_array.Item( i ); if( -1 == key_db_index ) continue; bool selected = InArray(m_active_index_array, key_db_index); if( ChartData->GetDBChartType( key_db_index ) == CHART_TYPE_CM93 || ChartData->GetDBChartType( key_db_index ) == CHART_TYPE_CM93COMP ) { if(selected) dc.SetBrush( m_scBrush ); else dc.SetBrush( m_cBrush ); } else if( ChartData->GetDBChartFamily( key_db_index ) == CHART_FAMILY_VECTOR ) { if(selected) dc.SetBrush( m_svBrush ); else dc.SetBrush( m_vBrush ); } else { // Raster Chart if(selected) dc.SetBrush( m_slBrush ); else dc.SetBrush( m_tBrush ); } #if 0 // Check to see if this box appears in the sub_light array // If so, add a crosshatch pattern to the brush if(InArray(m_eclipsed_index_array, key_db_index)) { wxBrush ebrush( dc.GetBrush().GetColour(), wxCROSSDIAG_HATCH ); dc.SetBrush(ebrush); } #endif if(m_bBusy) dc.SetBrush( m_uvBrush ); wxRect box = KeyRect.Item( i ); box.y += y; if( m_brounded ) { dc.DrawRoundedRectangle( box.x, box.y, box.width, box.height, 4 ); if(shapeDC) shapeDC->DrawRoundedRectangle( box.x, box.y, box.width, box.height, 4 ); } else { dc.DrawRectangle( box.x, box.y, box.width, box.height ); if(shapeDC) shapeDC->DrawRectangle( box ); } if(InArray(m_eclipsed_index_array, key_db_index)) { dc.SetBrush( m_backBrush ); int w = 3; dc.DrawRoundedRectangle( box.x + w, box.y + w, box.width - ( 2 * w ), box.height - ( 2 * w ), 3 ); } // Look in the current noshow array for this index if(InArray(m_noshow_index_array, key_db_index) && m_pInVizIconBmp && m_pInVizIconBmp->IsOk() ) dc.DrawBitmap(ConvertTo24Bit( dc.GetBrush().GetColour(), *m_pInVizIconBmp ), box.x + 4, box.y + 3, false ); // Look in the current skew array for this index if(InArray(m_skew_index_array, key_db_index) && m_pSkewIconBmp && m_pSkewIconBmp->IsOk()) dc.DrawBitmap(ConvertTo24Bit( dc.GetBrush().GetColour(), *m_pSkewIconBmp ), box.x + box.width - m_pSkewIconBmp->GetWidth() - 4, box.y + 2, false ); // Look in the current tmerc array for this index if(InArray(m_tmerc_index_array, key_db_index) && m_pTmercIconBmp && m_pTmercIconBmp->IsOk() ) dc.DrawBitmap(ConvertTo24Bit( dc.GetBrush().GetColour(), *m_pTmercIconBmp ), box.x + box.width - m_pTmercIconBmp->GetWidth() - 4, box.y + 2, false ); // Look in the current poly array for this index if(InArray(m_poly_index_array, key_db_index) && m_pPolyIconBmp && m_pPolyIconBmp->IsOk() ) dc.DrawBitmap(ConvertTo24Bit( dc.GetBrush().GetColour(), *m_pPolyIconBmp ), box.x + box.width - m_pPolyIconBmp->GetWidth() - 4, box.y + 2, false ); } }
void ProcessNextChar(char c) { if (c == '\n') { state = jsBegin; // abandon current parse (if any) and start again return; } switch (state) { case jsBegin: // initial state, expecting '{' if (c == '{') { parser_watcher::StartReceivedMessage(); state = jsExpectId; fieldVal.clear(); fieldId.clear(); arrayDepth = 0; } break; case jsExpectId: // expecting a quoted ID switch (c) { case ' ': // ignore space break; case '"': state = jsId; break; case '}': // empty object, or extra comma at end of field list RemoveLastId(); if (fieldId.size() == 0) { // TODO: should we report this to the monitor as an error? parser_watcher::EndReceivedMessage(); state = jsBegin; } else { RemoveLastIdChar(); state = jsEndVal; } break; default: state = JsError(); break; } break; case jsId: // expecting an identifier, or in the middle of one switch (c) { case '"': state = jsHadId; break; default: if (c < ' ') { state = JsError(); } else if (c != ':' && c != '^') { if (!fieldId.add(c)) { state = JsError(); } } break; } break; case jsHadId: // had a quoted identifier, expecting ':' switch (c) { case ':': state = jsVal; break; case ' ': break; default: state = JsError(); break; } break; case jsVal: // had ':' or ':[', expecting value switch (c) { case ' ': break; case '"': fieldVal.clear(); state = jsStringVal; break; case '[': if (arrayDepth < MAX_ARRAY_NESTING && fieldId.add('^')) { arrayIndices[arrayDepth] = 0; // start an array ++arrayDepth; } else { state = JsError(); } break; case ']': if (InArray()) { EndArray(); // empty array state = jsEndVal; } else { state = JsError(); // ']' received without a matching '[' first } break; case '-': fieldVal.clear(); // TODO: an report error to the watcher state = (fieldVal.add(c)) ? jsNegIntVal : JsError(); break; case '{': // start of a nested object // TODO: report an error to the watcher state = (fieldId.add(':')) ? jsExpectId : JsError(); break; default: if (c >= '0' && c <= '9') { fieldVal.clear(); fieldVal.add(c); // must succeed because we just cleared fieldVal state = jsIntVal; break; } else { state = JsError(); } } break; case jsStringVal: // just had '"' and expecting a string value switch (c) { case '"': ConvertUnicode(); ProcessField(); state = jsEndVal; break; case '\\': state = jsStringEscape; break; default: if (c < ' ') { state = JsError(); } else { fieldVal.add(c); // ignore any error so that long string parameters // just get truncated } break; } break; case jsStringEscape: // just had backslash in a string if (!fieldVal.full()) { switch (c) { case '"': case '\\': case '/': if (!fieldVal.add(c)) { state = JsError(); } break; case 'n': case 't': if (!fieldVal.add(' ')) // replace newline and tab by space { // parser_watcher::ProcessError(); state = JsError(); } break; case 'b': case 'f': case 'r': default: break; } } state = jsStringVal; break; case jsNegIntVal: // had '-' so expecting a integer value // TODO: report an error to the watcher state = (c >= '0' && c <= '9' && fieldVal.add(c)) ? jsIntVal : JsError(); break; case jsIntVal: // receiving an integer value switch (c) { case '.': state = (fieldVal.add(c)) ? jsFracVal : JsError(); break; case ',': ProcessField(); if (InArray()) { ++arrayIndices[arrayDepth - 1]; fieldVal.clear(); state = jsVal; } else { RemoveLastId(); state = jsExpectId; } break; case ']': if (InArray()) { ProcessField(); ++arrayIndices[arrayDepth - 1]; EndArray(); state = jsEndVal; } else { state = JsError(); } break; case '}': if (InArray()) { state = JsError(); } else { ProcessField(); RemoveLastId(); if (fieldId.size() == 0) { parser_watcher::EndReceivedMessage(); state = jsBegin; } else { RemoveLastIdChar(); state = jsEndVal; } } break; default: if (!(c >= '0' && c <= '9' && fieldVal.add(c))) { state = JsError(); } break; } break; case jsFracVal: // receiving a fractional value switch (c) { case ',': ProcessField(); if (InArray()) { ++arrayIndices[arrayDepth - 1]; state = jsVal; } else { RemoveLastId(); state = jsExpectId; } break; case ']': if (InArray()) { ProcessField(); ++arrayIndices[arrayDepth - 1]; EndArray(); state = jsEndVal; } else { state = JsError(); } break; case '}': if (InArray()) { state = JsError(); } else { ProcessField(); RemoveLastId(); if (fieldId.size() == 0) { parser_watcher::EndReceivedMessage(); state = jsBegin; } else { RemoveLastIdChar(); state = jsEndVal; } } break; default: if (!(c >= '0' && c <= '9' && fieldVal.add(c))) { state = JsError(); } break; } break; case jsEndVal: // had the end of a string or array value, expecting comma // or ] or } switch (c) { case ',': if (InArray()) { ++arrayIndices[arrayDepth - 1]; fieldVal.clear(); state = jsVal; } else { RemoveLastId(); state = jsExpectId; } break; case ']': if (InArray()) { ++arrayIndices[arrayDepth - 1]; EndArray(); } else { state = JsError(); } break; case '}': if (InArray()) { state = JsError(); } else { RemoveLastId(); if (fieldId.size() == 0) { parser_watcher::EndReceivedMessage(); state = jsBegin; } else { RemoveLastIdChar(); // state = jsEndVal; // not needed, state == jsEndVal already } } break; default: break; } break; case jsError: // Ignore all characters. State will be reset to jsBegin at the start of // this function when we receive a newline. break; } }