2011-11-12 11 views
5

Así que estoy haciendo un control de edición personalizado. Para hacer un seguimiento del contenido del control de edición, estoy usando una matriz de caracteres dinámicamente asignada.¿Cuál es la mejor manera de implementar un búfer para un control de edición de texto?

  • Ahora, sé que tengo que insertar en el medio de la matriz en ciertas situaciones, tales como cuando el usuario hace clic en un punto particular. Entonces, estaba pensando, en lugar de una matriz de caracteres, puedo usar std :: vector, así que podría usar la función .insert, y también no tendría que importar mucho sobre la administración de memoria.
  • También estaba pensando en almacenar directamente el flujo de entrada en una matriz/vector de palabras (sin mantener un búfer continuo), ya que mi propósito con este es implementar resaltado de sintaxis.

¿Cuál sería un mejor enfoque para hacer las cosas? ¿Y por qué?

Respuesta

4

Para un búfer de texto con las computadoras actuales puede simplemente usar un único búfer contiguo (por ejemplo, un vector) porque las CPU son lo suficientemente rápidas para hacer que el tiempo de inserción (una operación o(n) con este enfoque ingenuo) sea una opción viable.

En el pasado, cuando las computadoras eran miles de veces más lentas, un enfoque simple común era mantener el texto en un búfer pero con un "orificio" correspondiente a la posición del cursor, insertar o(1) y mover caracteres desde un lado del agujero al otro cuando el cursor se estaba moviendo en el texto (básicamente haciendo que el movimiento del cursor sea una operación o(k) donde k es el número de caracteres omitidos).

Para un editor diseñado para programadores, el texto se subdividirá en líneas lógicas y, por lo tanto, utilizar un enfoque basado en una serie de punteros a líneas parece apropiado. Incluso si esto hace que algunas operaciones de líneas cruzadas sean algo molestas, algunas operaciones basadas en líneas serán más fáciles ... la numeración de líneas en la pantalla se convierte en un problema trivial, especialmente si no necesitas implementar el ajuste de línea (horrible con el código) yendo para el truncamiento y el desplazamiento horizontal en su lugar.

+0

¡Esa es una explicación muy agradable, gracias! Sí, el texto se dividirá en líneas lógicas, y voy con desplazamiento horizontal. – devjeetroy

+2

Los editores que usan un búfer contiguo sufren terriblemente al editar archivos masivos (como un archivo de registro). Para los archivos fuente está bien, pero la gente inevitablemente quiere cargar _todo_ en su editor. Por lo tanto, se requiere algún tipo de segmentación. –

2

Es posible que necesite una representación doble, por lo tanto, tenga un vector de caracteres y un vector de palabras (el problema es mantenerlos sincronizados).

Sugiero también buscar, y tal vez incluso utilizar, un conjunto de herramientas gráficas cuya fuente está disponible gratuitamente, y que se pueden personalizar. (No soy de Windows, pero) estaba pensando, por ejemplo. de Qt que es una biblioteca gráfica de código abierto en C++ que se ejecuta en Windows, Linux, MacOSX, ...

No puedo ayudar más, porque no sé y no uso Windows (todas mis máquinas son bajo Linux).

+0

Gracias por la respuesta hombre! Definitivamente los investigaré una vez que haga lo mío. Primero quiero conocer todas las cosas "debajo del capó". También estaba pensando que podría haber una necesidad de representación dual. ¿Esto tiene un impacto en el rendimiento/uso de la memoria? ¿Y qué tal mantener un vector de caracteres y un vector de posiciones de cada palabra? Al igual que la posición de inicio y la longitud (utilizando una estructura)? ¿Sería eso un mejor rendimiento sabio? – devjeetroy

+0

** la optimización prematura es mala ** así que primero codifique una implementación correcta, cámbiela usando un generador de perfiles, y luego optimícela –

+0

En realidad, solo quiero obtener una vista de hacia dónde debo ir con el código, para que yo no No termina perdiendo el tiempo cuando podría haberse evitado fácilmente eligiendo el enfoque correcto para el problema – devjeetroy

4

El mejor enfoque es comenzar desde la edición del sistema o el control richedit y adaptarlo a sus necesidades. Escribir su propio control de edición es mucho más trabajo del que posiblemente pueda darse cuenta, incluido el manejo de accesibilidad, IME para idiomas con alfabetos complejos, copiar y pegar, barras de desplazamiento, cursores, selecciones y mucho más.

Los dos controles del sistema proporcionan muchos puntos de extensión que deberían permitirle alcanzar la mayoría de los objetivos. A menos que esté realmente construyendo un procesador de palabras o un editor de código fuente, debe apegarse a los provistos. Y los controles de edición personalizados son una fuente masiva de errores. Pocas veces veo uno que funcione bien solo para los casos básicos.

Martyn

+0

Estoy construyendo un editor de código fuente. Ya probé richedit y subclases no es tan rápido como me gustaría. Usé el método de over-write y setcharformat, pero no eran muy claros, por así decirlo. Empecé con mi control de edición personalizado y ya implementé el cursor y la entrada de varias líneas. Entonces, ahora estoy tratando de prepararlo para la selección de texto y la selección de varias líneas y cosas – devjeetroy

+0

Si realmente está construyendo un editor de código fuente, entonces implementar su propio búfer es la idea correcta. A la mayoría de los editores de código fuente se les pide que carguen archivos muy grandes (por ejemplo, registros del servidor), así que asegúrese de pensar detenidamente acerca de la gran escalabilidad O de las operaciones básicas. –

+0

sí, gracias hombre!Esa es una de mis principales consideraciones – devjeetroy

3

Si está pensando en algo así como un visor de código fuente (ref: "para poner en práctica el resaltado de sintaxis") con un almacén de respaldo mutable, es posible std::list<std::string> un buen punto de partida, y que puede ser excesiva si la cuerda es pequeña

Con un búfer contiguo para el texto (por ejemplo, un gran std::string o std::vector), tendrá mucho movimiento y cambio de tamaño durante la edición, así como una gran cantidad de exploración al reposicionar. Esos movimientos y cambios de tamaño darán como resultado muchas asignaciones grandes y contiguas, la inicialización del búfer, el movimiento y la liberación de la memoria anterior. También restringe la forma en que almacena datos en caché (si eso es importante). Sus tiempos de búsqueda serán un poco más lentos con una lista, pero sus movimientos y mutaciones serán mucho más rápidos que usar un buffer contiguo para todo el archivo.

std::list<std::string> tiene algunas buenas propiedades, ya que crece y muta como una colección de cadenas (por ejemplo, para cada línea o párrafo) muy bien.

Detalles Este panorama fortalezas de la lista y lo compara con otros recipientes, así: http://www.cplusplus.com/reference/stl/list/

Si desea asociar algunos datos de la cadena/de la línea, a continuación, basta con crear una lista de estos:

namespace MON { 
class t_line { 
public: 
    /* ... */ 
private: 
    std::string d_string; 
    t_lexer_stuff d_lexerStuff; 
}; 
} 
2

bien la búsqueda de la misma delgada me encontré con dos páginas de Wikipedia que fue muy servicial:

Gap buffer para la edición sencilla

Rope (data structure) para la edición de texto complejo

+0

Mi intento de un búfer de brecha en cpp: https://github.com/cmaughan/gapbuffer – cmaughan

Cuestiones relacionadas